TyXML Ppx syntax extension

TyXML provides a ppx to allow writing HTML and SVG documents in the standard syntax while still enjoying the benefits and type-safety of TyXML. For the ppx to be available, you need to install markup and ppx_tools. A convenience package tyxml-ppx is provided:

opam install tyxml-ppx

Syntax

The ppx provides two quotations, html and svg (and two aliases, tyxml.html and tyxml.svg).

open Tyxml ;;

let content = [%html{|<div id="content">some content</div>|}] ;;
val content : [> Html_types.div ] Html.elt

let svgpath = [%svg{|<path d="M 0 1 L 1 0"></path>|}] ;;
val svgpath : [> Svg_types.path ] Svg.elt

The quotations will use the Html and Svg module that are available in scope. To use another module name, you can qualify the quotation:

let content = [%html.F {|<div id="content">some content</div>|}]
val content : [> Html_types.div ] F.elt

A quotation containing multiple elements will automatically produce a list of elements:

let my_text = [%html
  {|This is an <b>HTML</b> formated <i>content</i>.|}]
val my_text : [> `B | `I | `PCDATA ] Html.elt list

The produced elements can be used inside usual TyXML combinators:

let my_span = Html.(span ~a:[a_class ["mytext"]] my_text)
val my_span : [> Html_types.span ] Html.elt

It is also possible to use tyxml elements inside quotations using #antiquotations#:

let my_paragraphs =
  [%html "<p>"[my_span]"</p><p>more content</p>"]
val my_paragraphs : [> Html_types.p ] Html.elt list

Note here that since p expects a list of children (it's a star element), the antiquotation must be of type list, hence the use of [, ].

It is also possible to use antiquotations for attributes.

let my_id = "thediv"
let my_div = [%html "<div id="my_id"></div>"]
val my_div : [> Html_types.div ] Html.elt

Let notation

It is also possible to use the ppx with the let notation:

let%html content = {|<div id="content">some content</div>|} ;;
val content : [> Html_types.div ] Html.elt

All the capabilities provided by the ppx are still available with this form. Additionally, the modifiers and or rec are available. It is also possible to create functions:

let%html make_content id = "<div id="id" >some content</div>" ;;
val make_content : string -> [> Html_types.div ] Html.elt

Notes

Locations

Due to the code transformations done by the ppx, proper locations are difficult to provide. Please report examples of badly located code on the bug tracker.

Composability

Due to various reasons, some HTML can not be composed properly using the ppx. For example, this will result in an error:

let my_title = [%html "<title>The title</title>"]
let my_head = [%html "<head>"my_title"</head>"]

You can, however, inline the title element inside the head element:

let my_title = [%html "The title"]
let my_head = [%html "<head><title>"my_title"</title></head>"]