252

I hate reST but love Sphinx. Is there a way that Sphinx reads Markdown instead of reStructuredText?

bad_coder
  • 11,289
  • 20
  • 44
  • 72
digi604
  • 2,636
  • 2
  • 17
  • 5
  • 1
    I'm not aware of any option available for this. But do note that RST has much more options than markdown in terms of extensibility. So depending on your project it might not be sufficient. – Wolph Mar 21 '10 at 13:58
  • 4
    There is a [subset of rST](https://gist.github.com/dupuy/1855764) that is mostly valid markdown. If you hate Sphinx field lists (`:param path:` etc), see [Napoleon extension](https://pypi.python.org/pypi/sphinxcontrib-napoleon/). – Beni Cherniavsky-Paskin Apr 07 '14 at 22:21
  • 3
    If you'd like to document your Python project in Markdown with Sphinx, vote for the feature request at https://bitbucket.org/birkenfeld/sphinx/issue/825/markdown-capable-sphinx – Colonel Panic Sep 14 '14 at 17:26
  • 1
    Looking at this comment, it seems as though you can mix the two: https://read-the-docs.readthedocs.org/en/latest/getting_started.html#in-markdown – Stefan van der Walt Jul 24 '15 at 02:18
  • If you don't mind not using Sphinx, there are a [bunch of tools](http://stackoverflow.com/questions/15402512/whole-site-compilation-of-markdown-pandoc) that do a similar job using markdown. – naught101 Oct 16 '15 at 05:50
  • 3
    Basic Markdown support has finally made it's way into Sphinx: see [new answer](http://stackoverflow.com/a/36103903/2626627) – Oliver Bestwalter Mar 19 '16 at 16:08
  • There's also a solution for inline Markdown doctrings with Sphinx using `pandoc` [here](https://github.com/embolalia/Sphinx-Pandoc). – 0 _ Apr 11 '16 at 09:38
  • @Wolph I'm running into this very problem right now - having to consider switching my documentation from mkdocs to sphinx due to lack of certain features requiring me to use HTML hacks. – Breakthrough Aug 18 '18 at 04:11
  • @breakthrough has native support for markdown these days so that's an option. But it's actually not too hard to extend sphinx either, so both could be options – Wolph Aug 18 '18 at 12:10
  • @Wolph thanks for the reply - since then have just decided to bite the bullet and switch to Sphinx (you can [check out the result here](http://manual.scenedetect.com) if you're interested). – Breakthrough Sep 15 '18 at 02:26

12 Answers12

126

You can use Markdown and reStructuredText in the same Sphinx project. How to do this is succinctly documented in the Sphinx documentation.

Install myst-parser (pip install myst-parser) and then edit conf.py:

# simply add the extension to your list of extensions
extensions = ['myst_parser']

source_suffix = ['.rst', '.md']

I've created a small example project on Github (serra/sphinx-with-markdown) demonstrating how (and that) it works. It uses Sphinx version 3.5.4 and myst-parser version 0.14.0.

In fact, MyST parser allows you to write your entire Sphinx documentation in Markdown. It supports directives and has several extensions you can enable through configuration in conf.py.

MyST parser requires Sphinx 2.1 or later. For earlier versions of Sphinx, you could use Markdown in Sphinx using recommonmark. Checkout earlier revisions of this answer to find out how.

Marijn
  • 10,367
  • 5
  • 59
  • 80
  • 6
    Beni mentions this approach in his [very comprehensive answer above](http://stackoverflow.com/a/2487862/322283). However, I feel this question deserves this simple answer. – Marijn Nov 19 '15 at 07:42
  • 2
    It's important to read https://recommonmark.readthedocs.org/en/latest/auto_structify.html, especially how to create a toctree, and how to use [`eval_rst` fenced block](https://recommonmark.readthedocs.org/en/latest/auto_structify.html#embed-restructuredtext) to insert any rST construct/directive. – Beni Cherniavsky-Paskin Dec 02 '15 at 09:37
  • this required to install recommonmark and commonmark – XavierCLL Apr 30 '16 at 03:40
  • 1
    I get `ImportError: cannot import name 'DocParser'` on Sphinx 1.4.1 under Python 3.4.3. – detly May 22 '16 at 04:52
  • 2
    @detly: The ImportError is due to the latest version of commonmark (0.6.0) breaking compatibility with recommonmark: see https://github.com/rtfd/recommonmark/issues/24. The solution: `pip install commonmark==0.5.5 --upgrade` – kadee Aug 08 '16 at 14:57
  • Pls note that current version of recommonmark doesn't supports tables – zhukovgreen Aug 14 '17 at 08:12
  • recommonmark is deprecated in favor of myst-parser https://github.com/readthedocs/recommonmark/issues/221 – astrojuanlu May 06 '21 at 09:42
  • 1
    That's interesting @astrojuanlu, thanks for sharing. I'll see if I can update my project on github using this recommendation. – Marijn May 06 '21 at 13:23
  • 2
    Thanks again @astrojuanlu. I reviewed my project and updated it to use myst-parser, works like a charm! – Marijn May 06 '21 at 15:03
106

The "proper" way to do that would be to write a docutils parser for markdown. (Plus a Sphinx option to choose the parser.) The beauty of this would be instant support for all docutils output formats (but you might not care about that, as similar markdown tools already exist for most). Ways to approach that without developing a parser from scratch:

  1. You could cheat and write a "parser" that uses Pandoc to convert markdown to RST and pass that to the RST parser :-).

  2. You can use an existing markdown->XML parser and transform the result (using XSLT?) to the docutils schema.

  3. You could take some existing python markdown parser that lets you define a custom renderer and make it build docutils node tree.

  4. You could fork the existing RST reader, ripping out everything irrelevant to markdown and changing the different syntaxes (this comparison might help)...
    EDIT: I don't recommend this route unless you're prepared to heavily test it. Markdown already has too many subtly different dialects and this will likely result in yet-another-one...

UPDATE: https://github.com/sgenoud/remarkdown is a markdown reader for docutils. It didn't take any of the above shortcuts but uses a Parsley PEG grammar inspired by peg-markdown.

UPDATE: https://github.com/readthedocs/recommonmark and is another docutils reader, natively supported on ReadTheDocs. Derived from remarkdown but uses the CommonMark-py parser.

  • It can convert specific more-or-less natural Markdown syntaxes to appropriate structures e.g. list of links to a toctree. * Doesn't have generic native syntax for roles.
  • Supports embedding any rST content, including directives, with an ```eval_rst fenced block as well as a shorthand for directives DIRECTIVE_NAME:: ....

UPDATE: MyST is yet another docutins/Sphinx reader. Based on markdown-it-py, CommonMark compatible.

  • Has a generic {ROLE_NAME}`...` syntax for roles.
  • Has a generic syntax for directives with ```{DIRECTIVE_NAME} ... fenced blocks.

In all cases, you'll need to invent extensions of Markdown to represent Sphinx directives and roles. While you may not need all of them, some like .. toctree:: are essential.
This I think is the hardest part. reStructuredText before the Sphinx extensions was already richer than markdown. Even heavily extended markdown, such as pandoc's, is mostly a subset of rST feature set. That's a lot of ground to cover!

Implementation-wise, the easiest thing is adding a generic construct to express any docutils role/directive. The obvious candidates for syntax inspiration are:

  • Attribute syntax, which pandoc and some other implementations already allow on many inline and block constructs. For example `foo`{.method} -> `foo`:method:.
  • HTML/XML. From <span class="method">foo</span> to the kludgiest approach of just inserting docutils internal XML!
  • Some kind of YAML for directives?

But such a generic mapping will not be the most markdown-ish solution... Currently most active places to discuss markdown extensions are https://groups.google.com/forum/#!topic/pandoc-discuss, https://github.com/scholmd/scholmd/

This also means you can't just reuse a markdown parser without extending it somehow. Pandoc again lives up to its reputation as the swiss army knife of document conversion by supporting custom filtes. (In fact, if I were to approach this I'd try to build a generic bridge between docutils readers/transformers/writers and pandoc readers/filters/writers. It's more than you need but the payoff would be much wider than just sphinx/markdown.)


Alternative crazy idea: instead of extending markdown to handle Sphinx, extend reStructuredText to support (mostly) a superset of markdown! The beauty is you'll be able to use any Sphinx features as-is, yet be able to write most content in markdown.

There is already considerable syntax overlap; most notably link syntax is incompatible. I think if you add support to RST for markdown links, and ###-style headers, and change default `backticks` role to literal, and maybe change indented blocks to mean literal (RST supports > ... for quotations nowdays), you'll get something usable that supports most markdown.

Beni Cherniavsky-Paskin
  • 9,483
  • 2
  • 50
  • 58
  • 17
    I conclude from the lack of progress in this area, the ReST may just be good enough and not sufficiently dissimilar so Markdown for such an undertaking to be worth it. – Prof. Falken Feb 04 '13 at 13:04
  • 5
    TLDR: Use [recommonmark](https://github.com/rtfd/recommonmark) to write Sphinx documentation using Markdown. – ostrokach Apr 04 '16 at 00:19
  • 5
    Currently this is the most upvoted answer, but it's a difficult to read collection of old alternatives and updates. In particular, recommonmark is deprecated in favor of myst-parser https://github.com/readthedocs/recommonmark/issues/221 – astrojuanlu May 06 '21 at 09:41
34

This doesn't use Sphinx, but MkDocs will build your documentation using Markdown. I also hate rst, and have really enjoyed MkDocs so far.

juliocesar
  • 5,706
  • 8
  • 44
  • 63
jkmacc
  • 6,125
  • 3
  • 30
  • 27
  • 6
    MkDocs have worked really well here too, for end-user documentation. Still looking to use markdown within docstrings.. – Marcus Ottosson May 15 '14 at 15:11
  • 1
    Hey, thanks — [MkDocs](http://www.mkdocs.org/) is awesome! I loose a lot of power and features compared to Sphinx and RST, that's for sure… but it is awesomely uncomplicated, streamlined and so easy and fast to use. Perfect for almost all of my use cases — like short install instructions and some quick start tutorial with some examples. For the few cases, where I need lots of source code explaining — i.g. class and function call documentation — I stick with Sphinx though. – Brutus Aug 14 '15 at 11:52
  • At the time of writing this, it supports only 2 levels of TOC indentation though. – wrygiel Jan 09 '16 at 09:23
  • @wrygiel You're not quite right — the number of TOC levels rendered depends on the theme you're using. – Ale Feb 01 '16 at 18:45
33

Update May 2021: recommonmark is deprecated in favour of myst-parser (thanks astrojuanlu)

Update: this is now officially supported and documented in the sphinx docs.

It looks like a basic implementation has made it's way into Sphinx but word has not gotten round yet. See github issue comment

install dependencies:

pip install commonmark recommonmark

adjust conf.py:

source_parsers = {
    '.md': 'recommonmark.parser.CommonMarkParser',
}
source_suffix = ['.rst', '.md']
Oliver Bestwalter
  • 5,219
  • 33
  • 47
20

Markdown and ReST do different things.

RST provides an object model for working with documents.

Markdown provides a way to engrave bits of text.

It seems reasonable to want to reference your bits of Markdown content from your sphinx project, using RST to stub out the overall information architecture and flow of a larger document. Let markdown do what it does, which is allow writers to focus on writing text.

Is there a way to reference a markdown domain, just to engrave the content as-is? RST/sphinx seems to have taken care of features like toctree without duplicating them in markdown.

bewest
  • 316
  • 2
  • 5
  • 5
    "It seems reasonable to want to reference your bits of Markdown content from your sphinx project" — this is actually what I want to do; I want to include some markdown content (my `README.md`) in my more comprehensive Sphinx documentation. Do you know if this is possible? – detly Apr 29 '14 at 12:45
  • Docutils provides an object model for working with documents, not RST. reST is just one language that can be parsed into a Docutils tree. Markdown is another such language, thanks to frontends like reCommonMark and MyST. – Clément Sep 20 '21 at 17:38
16

I recommend using MyST Markdown. This is a flavor of Markdown that was designed to bring in the major features of reStructuredText. MyST stands for Markedly Structured Text, and can be thought of as "rST but with Markdown".

MyST is a superset of the CommonMark standard, and it is defined as a collection of discrete extensions to CommonMark via the markdown-it-py package). This means that CommonMark syntax works out-of-the-box with MyST, but you can also use more syntax features if you wish.

MyST has syntax for virtually every feature in reStructuredText, and it is tested against the full Sphinx test suite to ensure that the same functionality can be re-created. For example:

Here is how you write a directive in MyST:

```{directivename} directive options
:key: value
:key2: value2

Directive content
```

And here is how you write a role in MyST

Here's some text and a {rolename}`role content`

The Sphinx parser for MyST Markdown also has some nice Sphinx-specific features, like using Markdown link syntax ([some text](somelink)) to also handle cross-references in Sphinx. So for example, you can define a label in MyST, and reference it, like so:

(my-label)=
# My header

Some text and a [cross reference](my-label).

For a more complete list of MyST Markdown syntax, a good reference is the Jupyter Book cheatsheet, which has a list of many common document needs and the respective MyST syntax to accomplish it. (MyST was created as a component of Jupyter Book, though it exists as a totally standalone project from a technical perspective).

MyST is now the recommended Markdown tool for Sphinx in the Sphinx docs as well as the ReadTheDocs documentation.

To add the MyST Parser to your Sphinx documentation, simply do the following:

pip install myst-parser

And in conf.py, add:

extensions = [
  ...
  "myst_parser",
  ...
]

Your Sphinx documentation will now be able to parse CommonMark markdown as well as the extended MyST Markdown syntax! Check out the MyST Documentation for more information!

I hope that this helps clarify some things!

john-hen
  • 4,410
  • 2
  • 23
  • 40
choldgraf
  • 3,539
  • 4
  • 22
  • 27
  • 4
    This is the answer this question deserves :) – astrojuanlu May 06 '21 at 14:54
  • May I use `doxygen directive using breathe` in markdown file? [Source](https://breathe.readthedocs.io/en/latest/directives.html#doxygenclass). Suppose in any sample.rst file if I write `.. doxygenclass:: A::B::Base`, it gives a total doc of this class. But how to write it in `markdown` if my file name is `sample.md`? – user10634362 Dec 09 '21 at 15:36
14

This is now officially supported: http://www.sphinx-doc.org/en/stable/markdown.html

See also https://myst-parser.readthedocs.io/en/latest/syntax/optional.html for extensions, including linkify to make urls automatic links.

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Clément
  • 12,299
  • 15
  • 75
  • 115
8

I went with Beni's suggestion of using pandoc for this task. Once installed the following script will convert all markdown files in the source directory to rst files, so that you can just write all your documentation in markdown. Hope this is useful for others.

#!/usr/bin/env python
import os
import subprocess

DOCUMENTATION_SOURCE_DIR = 'documentation/source/'
SOURCE_EXTENSION = '.md'
OUTPUT_EXTENSION = '.rst'

for _, __, filenames in os.walk(DOCUMENTATION_SOURCE_DIR):
    for filename in filenames:
        if filename.endswith('.md'):
            filename_stem = filename.split('.')[0]
            source_file = DOCUMENTATION_SOURCE_DIR + filename_stem + SOURCE_EXTENSION
            output_file = DOCUMENTATION_SOURCE_DIR + filename_stem + OUTPUT_EXTENSION
            command = 'pandoc -s {0} -o {1}'.format(source_file, output_file)
            print(command)
            subprocess.call(command.split(' '))
igniteflow
  • 8,404
  • 10
  • 38
  • 46
8

Here’s a new option. MyST adds some features to Markdown that allow Sphinx to build docs like rst does. https://myst-parser.readthedocs.io/en/latest/

jkmacc
  • 6,125
  • 3
  • 30
  • 27
1

There is a workaround.
The sphinx-quickstart.py script generates a Makefile.
You can easily invoke Pandoc from the Makefile every time you'd like to generate the documentation in order to convert Markdown to reStructuredText.

the_drow
  • 18,571
  • 25
  • 126
  • 193
  • 3
    Unless I'm doing something wrong, it's not that easy to replace ReST with Markdown. If you use instructions like [toctree](http://sphinx-doc.org/markup/toctree.html) in Markdown source file, then Pandoc will change them into a single line: `.. toctree:: :maxdepth: 2 :glob:` during transformation and they'll stop working. In other words, it's impossible to use directives this way. – Wiktor Walc May 20 '13 at 08:03
  • @WiktorWalc I'm not very familiar with pandoc and I haven't really tried it but it made sense I guess. Oh well. I tried. I guess you can file a bug report? – the_drow May 21 '13 at 22:06
  • @WiktorWalc: `..toctree` is not valid Markdown syntax. You either write the entire document in Markdown (and loose the niceties of ReSt), or you use ReST. You cannot have your cake and eat it too. – Aditya Sep 25 '13 at 19:02
  • 1
    just a hint: a solution would be to use pandoc filters to skip those special instructions and leave them as is in the output generation. I'm not a wizard of pandoc filters though, and it adds extra complexity to the scheme. – zmo Mar 06 '15 at 19:05
0

Note that building documentation using maven and embedded Sphinx + MarkDown support is fully supported by following maven plugin :

https://trustin.github.io/sphinx-maven-plugin/index.html

<plugin>
  <groupId>kr.motd.maven</groupId>
  <artifactId>sphinx-maven-plugin</artifactId>
  <version>1.6.1</version>
  <configuration>
    <outputDirectory>${project.build.directory}/docs</outputDirectory>
  </configuration>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>generate</goal>
      </goals>
    </execution>
  </executions>
</plugin>
Donatello
  • 3,486
  • 3
  • 32
  • 38
0

This is an update to the recommonmark approach.

pip install recommonmark

Personally I use Sphinx 3.5.1, so

# for Sphinx-1.4 or newer
extensions = ['recommonmark']

Check the official doc here.

Syscall
  • 19,327
  • 10
  • 37
  • 52
xiaoou wang
  • 891
  • 10
  • 13