[ANN] .mlx syntax dialect

Dear OCaml community,

it is my pleasure to announce a release of .mlx dialect.

The .mlx dialect extends OCaml syntax with JSX expression construct, following the example of JSX in JavaScript/ReasonML. A brief snippet:

let page ?(encoding="utf8") ~title ~content =
  <html>
    <head>
      <meta charset=encoding />
      <title>title</title>
    </head>
    <body>
      content
    </body>
  </html>

let _ = <page title="Hello" content="World" />

The main use case is to make it easier to describe user interfaces with OCaml, which can range from generating HTML (example with Dream) to describing interactive UIs with ReasonReact (example).

Installation and usage

Install the packages from opam:

opam install mlx ocamlmerlin-mlx

Then configure dune to use the mlx preprocessor:

(dialect
 (name mlx)
 (implementation
  (extension mlx)
  (merlin_reader mlx)
  (preprocess
   (run mlx-pp %{input-file}))))

Now files with .mlx extension will be treated as OCaml modules.

The merlin/ocamllsp users will get roughly the same level of support for .mlx syntax as they get for .ml but some additional text editor/IDE configuration is needed to associate .mlx files with merlin/ocamllsp.

For neovim users there’s a plugin ocaml-mlx/ocaml_mlx.nvim, which does that bit of a configuration and provides highlighting for .mlx files based on a tree-sitter parser.

28 Likes

In your example content is a parameter, i.e. a computed value. How would literal content look like?

The children of JSX elements are OCaml expressions, so you’d have to use a string:

<body>
  "content"
</body>

The grammar extension is intentionally pretty minimal to easy the maintenance. So it’s not trying to follow HTML very closely.

6 Likes

Looks great, that’s exactly what I was looking for. I’d love to use OCaml with Melange to write react apps but really don’t want to resort to Reason for this. Hopefully not too off topic: Any idea if the reason-react-ppx is going to work with the original OCaml-syntax so I can build the whole app in OCaml?

Yes! The link to ReasonReact example in the OP is doing exactly that — mlx syntax used with reason-react-ppx.

2 Likes

This is just great. Going to use this right away!

1 Like

Is there a reason for not following the JSX approach of enclosing code in HTML expressions in {}? Especially in OCaml, it seems confusing to me that

<body>
    f x
</body>

doesn’t have the result of the function application f x as child, but two children f and x.

2 Likes

Unfortunately there’s no good answer to that, the alternatives we’ve considered for JSX children syntax were:

  1. Implement it as it is now — as a list of simple expressions
  2. Use {..} brackets like you’ve suggested
  3. Use ; delimiter for a list of expressions

The 3. was ruled out as being to noisy. The 2. is also a good proposal but choice was made in favour of 1. partly because of simplicity.

I agree, it can seen confusing at first but the rule is simple — if that’a a non simple expressions (like application), then you wrap it with (..), as in normal .ml syntax.

Why not add these examples to the project readme, I would never have found them.

Good idea! Updated the README.

1 Like

Project looks great BTW, am keen to try it out!

1 Like

Has anyone made it work with TyXML?

A small follow up announcement, the new package ocamlformat-mlx has been released on opam. It’s a fork of ocamlformat with support for formatting .mlx syntax.

I’m not aware of integration with TyXML but for generating HTML there’s GitHub - davesnx/html_of_jsx: Render HTML with JSX by @davesnx