11[ ![ 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 )
22
3- ## mdx -- executable code blocks inside markdown files
3+ ## MDX
44
5- ` mdx ` allows to execute code blocks inside markdown files.
6- There are (currently) two sub-commands, corresponding
7- to two modes of operations: pre-processing (` ocaml-mdx pp ` )
8- and tests (` ocaml-mdx test ` ).
5+ MDX allows to execute code blocks inside markdown and mli documentation
6+ to help keeping them up to date.
97
10- The pre-processor mode allows to mix documentation and code,
11- and to practice "literate programming" using markdown and OCaml.
8+ Use the
9+ [ dune stanza] ( https://dune.readthedocs.io/en/latest/dune-files.html#mdx-since-2-4 )
10+ to enable it on your documentation.
1211
13- The test mode allows to ensure that shell scripts and OCaml fragments
14- in the documentation always stays up-to-date.
15-
16- ` mdx ` is released as a single binary (called ` ocaml-mdx ` ) and
17- can be installed using opam:
12+ ` mdx ` is released on opam and can be installed by running:
1813
1914``` sh
2015$ opam install mdx
2116```
2217
23- If you want to contribute or hack on the project, please see the
18+ If you want to contribute to the project, please see the
2419[ CONTRIBUTING.md] ( CONTRIBUTING.md ) .
2520
21+ ### Basic Usage
22+
23+ You can use MDX with your Markdown or ` .mli ` documentation, which ensures
24+ code in multi-line or verbatim code blocks is correct.
25+
26+ To enable MDX on specific files you must first enable it for your project by
27+ adding the following stanza to your ` dune-project ` :
28+ ```
29+ (using mdx 0.2)
30+ ```
31+
32+ Note that version ` 0.2 ` of the MDX stanza is only available in dune ` 3.0 ` or
33+ higher. You can use the first, ` 0.1 ` version with dune ` 2.4 ` or higher.
34+
35+ Then add the following in the relevant ` dune ` file:
36+ ```
37+ (mdx)
38+ ```
39+ That enables MDX on all markdown files in the folder.
40+ The MDX stanza can be further configured. Please visit the relevant section of
41+ [ dune's manual] ( https://dune.readthedocs.io/en/latest/dune-files.html#mdx-since-2-4 )
42+ for more information.
43+
44+ MDX supports various type of code blocks but the most common are OCaml toplevel
45+ blocks. We illustrate one in our example below. In a Markdown file, you
46+ would write something similar to this:
47+
48+ ```` markdown
49+ Let's look at how good OCaml is with integers and strings:
50+ ```ocaml
51+ # 1 + 2;;
52+ - : int = 2
53+ # "a" ^ "bc";;
54+ - : string = "ab"
55+ ```
56+ ````
57+ or in an ` mli ` file:
58+ ``` ocaml
59+ (** Let's look at how good OCaml is with integers and strings:
60+ {@ocaml[
61+ # 1 + 2;;
62+ - : int = 2
63+ # "a" ^ "bc";;
64+ - : string = "ab"
65+ ]}
66+ *)
67+ ```
68+
69+ The content of the toplevel blocks looks just like an interactive toplevel
70+ session. Phrases, i.e., the toplevel "input", start with a ` # ` and end with ` ;; ` .
71+ The toplevel evaluation, or "output" follows each phrase.
72+
73+ Now you probably have noticed that ` 1 + 2 ` is not equal to ` 2 ` nor is ` "a" ^ "bc" `
74+ to ` "ab" ` . Somebody must have updated the phrases, but then forgot to update
75+ the evaluation.
76+
77+ That's exactly why MDX is here!
78+
79+ If you enable MDX for this file and then ran ` dune runtest ` , this would be the
80+ result:
81+
82+ ````
83+ $ dune runtest
84+ File "README.md", line 1, characters 0-0:
85+ git (internal) (exit 1)
86+ (cd _build/default && /usr/bin/git --no-pager diff --no-index --color=always -u README.md .mdx/README.md.corrected)
87+ diff --git a/README.md b/.mdx/README.md.corrected
88+ index 181b86f..458ecec 100644
89+ --- a/README.md
90+ +++ b/.mdx/README.md.corrected
91+ @@ -1,13 +1,13 @@
92+ Let's look at how good OCaml is with integers and strings:
93+ ```ocaml
94+ # 1 + 2;;
95+ -- : int = 2
96+ +- : int = 3
97+ # "a" ^ "bc";;
98+ -- : string = "ab"
99+ +- : string = "abc"
100+ ```
101+ ````
102+
103+ The test run just failed and dune is showing the diff between what we have
104+ locally and what should be, according to MDX.
105+ This uses dune's promotion workflow so at this point you can either investigate
106+ it further if you're surprised by this diff or if you're happy with it, simply
107+ accept it by running:
108+
109+ ```
110+ dune promote
111+ ```
112+
113+ Now the documentation is up-to-date and running ` dune runtest ` again should be
114+ successful!
115+
26116### Supported Extensions
27117
28118#### Labels
29119
30- The blocks in markdown files can be parameterized by ` mdx ` -specific labels, that
120+ The blocks can be parameterized by ` mdx ` -specific labels, that
31121will change the way ` mdx ` interprets the block.
32122
33- The syntax is: ` <!-- $MDX LABELS --> ` , where ` LABELS ` is a list of valid labels
34- separated by a comma. This line has to immediately precede the block it is
35- attached to.
123+ The markdown syntax is: ` <!-- $MDX LABELS --> ` , where ` LABELS ` is a list of
124+ valid labels separated by a comma. This line has to immediately precede the
125+ block it is attached to.
36126
37127 <!-- $MDX LABELS -->
38128 ```ocaml
39129 ```
40130
41- This syntax is the recommended way to define labels since ` mdx ` 1.7.0, to use
42- the previous syntax please refer to the
43- [ mdx 1.6.0 README] ( https://github.com/realworldocaml/mdx/blob/1.6.0/README.md ) .
44-
45- It is also possible to use labels in OCaml interface files (` mli ` ), the syntax
46- for this is is slightly different to match the conventions of OCaml
47- documentation comments:
131+ The ` .mli ` syntax for this is is slightly different to match the conventions of
132+ OCaml documentation comments:
48133
49134 (** This is an documentation comment with an ocaml block
50135 {@ocaml LABELS [
@@ -93,7 +178,7 @@ with a padding of 3:
93178 10
94179 ```
95180
96- ` ocaml-mdx ` will also consider exit codes when the syntax ` [<exit code>] ` is used:
181+ MDX will also consider exit codes when the syntax ` [<exit code>] ` is used:
97182
98183 ```sh
99184 $ exit 1
@@ -105,7 +190,7 @@ of success).
105190
106191#### OCaml Code
107192
108- ` ocaml-mdx ` interprets OCaml fragments. It understands _ normal_ code fragments and
193+ MDX interprets OCaml fragments. It understands _ normal_ code fragments and
109194_ toplevel_ code fragments (starting with a ` # ` sign and optionally ending with
110195` ;; ` ). Arbitrary whitespace padding is supported, at long as it stays
111196consistent within a code block.
@@ -126,7 +211,8 @@ Here is an examples of toplevel OCaml code:
126211 ```
127212
128213### File sync
129- ` mdx ` is also capable of including content from files in fenced code blocks
214+
215+ MDX is also capable of including content from files in fenced code blocks
130216using the label ` file ` . OCaml files can be sliced using named blocks:
131217
132218``` ocaml
@@ -149,38 +235,6 @@ Non-OCaml files can also be read and included in a block:
149235 ```
150236However, part splitting is only supported for OCaml files.
151237
152- ### Pre-processing
153-
154- ` ocaml-mdx pp ` allows to transform a markdown file into a valid
155- OCaml file, which can be passed to OCaml using the ` -pp `
156- option.
157-
158- For instance, given the following ` file.md ` document:
159-
160- ```ocaml
161- # print_endline "42"
162- 42
163- ```
164-
165- Can be compiled and executed using:
166-
167- ``` sh
168- $ ocamlc -pp ' ocaml-mdx pp' -impl file.md -o file.exe
169- $ ./file.exe
170- 42
171- ```
172-
173- This can be automated using ` dune ` :
174-
175- ```
176- (rule
177- ((targets (file.ml))
178- (deps (file.md))
179- (action (with-stdout-to ${@} (run ocaml-mdx pp ${<})))))
180-
181- (executable ((name file)))
182- ```
183-
184238### Tests
185239
186240#### Cram Tests
@@ -209,51 +263,6 @@ To execute OCaml code and toplevel fragments, uses `ocaml-mdx test <file.md>`.
209263If the output is not consistent with what is expected
210264` <file.md>.corrected ` is generated.
211265
212- #### Integration with Dune
213-
214- To test that the code blocks of ` file.md ` stay consistent, one can use
215- dune's ` mdx ` stanza:
216-
217- ```
218- (mdx
219- (files file.md))
220- ```
221-
222- This allows to test the consistency of a markdown file using the normal dev
223- workflow:
224-
225- ```
226- $ dune runtest
227- ```
228-
229- will display a diff of the output if something has changed. For instance:
230-
231- ```
232- $ dune runtest
233- ------ file.md
234- ++++++ file.md.corrected
235- File "file.md", line 23, characters 0-1:
236- |
237- |```sh
238- -| $ for i in `seq 1 3`; do echo $i; done
239- +| $ for i in `seq 1 4`; do echo $i; done
240- | 1
241- | 2
242- | 3
243- +| 4
244- |```
245- ```
246-
247- And the changes can then be accepted using:
248-
249- ```
250- $ dune promote
251- ```
252-
253- For further details about the mdx stanza you should read the
254- [ according section] ( https://dune.readthedocs.io/en/latest/dune-files.html#mdx-since-2-4 )
255- in the dune documentation.
256-
257266#### Non-deterministic Tests
258267
259268** Non-deterministic Outputs**
@@ -373,10 +382,3 @@ Those variables are then available in the subsequent blocks
373382 bar
374383 - : unit = ()
375384 ```
376-
377- ### Sections
378-
379- It is possible to test or execute only a subset of the file using
380- sections using the ` --section ` option (short name is ` -s ` ). For
381- instance ` ocaml-mdx pp -s foo ` will only consider the section matching the
382- perl regular expression ` foo ` .
0 commit comments