Skip to content
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 108 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,134 @@
[![Build Status](https://img.shields.io/endpoint?url=https%3A%2F%2Fci.ocamllabs.io%2Fbadge%2Frealworldocaml%2Fmdx%2Fmain&logo=ocaml)](https://ci.ocamllabs.io/github/realworldocaml/mdx)

## mdx -- executable code blocks inside markdown files
## mdx -- executable code blocks inside documentation

`mdx` allows to execute code blocks inside markdown files.
There are (currently) two sub-commands, corresponding
to two modes of operations: pre-processing (`ocaml-mdx pp`)
and tests (`ocaml-mdx test`).
`mdx` allows to execute code blocks inside markdown and mli documentation
to help keeping them up to date.

The pre-processor mode allows to mix documentation and code,
and to practice "literate programming" using markdown and OCaml.
Use the
[dune stanza](https://dune.readthedocs.io/en/latest/dune-files.html#mdx-since-2-4)
to enable it on your documentation.

The test mode allows to ensure that shell scripts and OCaml fragments
in the documentation always stays up-to-date.

`mdx` is released as a single binary (called `ocaml-mdx`) and
can be installed using opam:
`mdx` is released on opam and can be installed by running:

```sh
$ opam install mdx
```

If you want to contribute or hack on the project, please see the
If you want to contribute to the project, please see the
[CONTRIBUTING.md](CONTRIBUTING.md).

### Basic Usage

You can use MDX with your Markdown or `.mli` documentation, which ensures
code in multi-line or verbatim code blocks is correct.

To enable MDX, you need to add `(mdx)` stanzas to the right `dune` files. Before
that you must enable MDX for your project by adding the following to
your `dune-project`:

```
(using mdx 0.2)
```

Then add the following in the relevant `dune` file:
```
(mdx)
```
That enables MDX on all markdown files in the folder.
The MDX stanza can be further configured. Please visit the relevant section of
[dune's manual](https://dune.readthedocs.io/en/latest/dune-files.html#mdx-since-2-4)
for more information.

MDX supports various type of code blocks but the most common are OCaml toplevel
blocks. We illustrate one in our example below. In a Markdown file, you
would write something similar to this:

````markdown
Let's look at how good OCaml is with integers and strings:
```ocaml
# 1 + 2;;
- : int = 2
# "a" ^ "bc";;
- : string = "ab"
```
````
or in an `mli` file:
```ocaml
(** Let's look at how good OCaml is with integers and strings:
{@ocaml[
# 1 + 2;;
- : int = 2
# "a" ^ "bc";;
- : string = "ab"
]}
*)
```

The content of the toplevel blocks looks just like an interactive toplevel
session. Phrases, i.e., the toplevel "input", start with a `#` and end with `;;`.
The toplevel evaluation, or "output" follows each phrase.

Now you probably have noticed that `1 + 2` is not equal to `2` nor is `"a" ^ "bc"`
to `"ab"`. Somebody must have updated the phrases, but then forgot to update
the evaluation.

That's exactly why MDX is here!

If you enable MDX for this file and then ran `dune runtest`, this would be the
result:

````
$ dune runtest
File "README.md", line 1, characters 0-0:
git (internal) (exit 1)
(cd _build/default && /usr/bin/git --no-pager diff --no-index --color=always -u README.md .mdx/README.md.corrected)
diff --git a/README.md b/.mdx/README.md.corrected
index 181b86f..458ecec 100644
--- a/README.md
+++ b/.mdx/README.md.corrected
@@ -1,13 +1,13 @@
Let's look at how good OCaml is with integers and strings:
```ocaml
# 1 + 2;;
-- : int = 2
+- : int = 3
# "a" ^ "bc";;
-- : string = "ab"
+- : string = "abc"
```
````

The test run just failed and dune is showing the diff between what we have
locally and what should be, according to MDX.
This uses dune's promotion workflow so at this point you can either investigate
it further if you're surprised by this diff or if you're happy with it, simply
accept it by running:

```
dune promote
```

Now the documentation is up-to-date and running `dune runtest` again should be
successful!

### Supported Extensions

#### Labels

The blocks in markdown files can be parameterized by `mdx`-specific labels, that
The blocks can be parameterized by `mdx`-specific labels, that
will change the way `mdx` interprets the block.

The syntax is: `<!-- $MDX LABELS -->`, where `LABELS` is a list of valid labels
separated by a comma. This line has to immediately precede the block it is
attached to.
The markdown syntax is: `<!-- $MDX LABELS -->`, where `LABELS` is a list of
valid labels separated by a comma. This line has to immediately precede the
block it is attached to.

<!-- $MDX LABELS -->
```ocaml
```

This syntax is the recommended way to define labels since `mdx` 1.7.0, to use
the previous syntax please refer to the
[mdx 1.6.0 README](https://github.com/realworldocaml/mdx/blob/1.6.0/README.md).

It is also possible to use labels in OCaml interface files (`mli`), the syntax
for this is is slightly different to match the conventions of OCaml
documentation comments:
The `.mli` syntax for this is is slightly different to match the conventions of
OCaml documentation comments:

(** This is an documentation comment with an ocaml block
{@ocaml LABELS [
Expand Down