Page
Library
Module
Module type
Parameter
Class
Class type
Source
Dream_htmlSourceConstructing HTML. Detailed explanation in https://github.com/yawaramin/dream-html.
Let's adapt the example from the Dream home page:
let hello who =
    let open Dream_html in
    let open Tag in
    html [] [body [] [h1 [] [txt "Hello, %s!" who]]]
  let () =
    Dream.run
    @@ Dream.logger
    @@ Dream.router [Dream.get "/" (fun _ -> Dream_html.respond (hello "world"))]More examples shown below.
These are the types of the final values which get rendered.
E.g. id="toast".
Either a tag, a comment, or text data in the markup.
val respond : 
  ?status:[< Dream.status ] ->
  ?code:int ->
  ?headers:(string * string) list ->
  node ->
  Dream.response Dream.promiseType-safe wrapper for Dream.set_body. Sets the body to the given node and sets the Content-Type header to text/html.
Type-safe wrapper for Dream.write.
Special handling for string-value attributes so they can use format strings i.e. string interpolation.
A 'void element': https://developer.mozilla.org/en-US/docs/Glossary/Void_element with no children.
Tags which can have attributes but can contain only text. The text can be formatted.
attr name is a new attribute which does not carry any payload. E.g.
let required = attr "required"string_attr name fmt is a new string-valued attribute which allows formatting i.e. string interpolation of the value. Note, the fmt argument is required due to the value restriction.
Convenience for attributes whose values should be URIs. Takes care of URI- encoding.
a [href "/blog?tags=iamsafe\"></a><script>alert('Pwned')</script>"] [txt "Tags: tag1 | tag2"]Output:
<a href="/blog?tags=iamsafe%22%3E%3C/a%3E%3Cscript%3Ealert('Pwned')%3C/script%3E">Tags: tag1 | tag2</a>A text node inside the DOM e.g. the 'hi' in <b>hi</b>. Allows string interpolation using the same formatting features as Printf.sprintf:
b [] [txt "Hello, %s!" name]Or without interpolation:
b [] [txt "Bold of you."]HTML-escapes the text value using Dream.html_escape. You can use the ~raw param to bypass escaping:
let user_input = "<script>alert('I like HTML injection')</script>" in
  txt ~raw:true "%s" user_inputA comment that will be embedded in the rendered HTML, i.e. <!-- comment -->. The text is HTML-escaped.
Convenience to add a CSRF token generated by Dream into your form. Type-safe wrapper for Dream.csrf_tag.
Tag.form
    [action "/foo"]
    [csrf_tag req; input [name "bar"]; input [type_ "submit"]]Get the value of an existing attribute.
let toast = p [id "toast"] [txt "OK."]
  let toast_id = toast.@["id"]Standard, most non-deprecated attributes from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes. Where an attribute name conflicts with an OCaml keyword, the name is suffixed with _. Most attributes are constructed by passing in a value of some type.
HTML tags. Most (standard tags) are constructed by passing a list of attributes and a list of children:
htmx attributes https://htmx.org/reference/#attributes
In this section we show an extended example of interoperability of dream-html with other formats, e.g. the Markdown format defined by the omd library:
open Dream_html
  open Tag
  open Attr
  let omd_attr (k, opt_v) =
    string_attr k "%s" @@ Option.fold ~none:"" ~some:Fun.id opt_v
  let rec omd_node elements = elements |> List.map element_node |> Tag.null
  and item omd = li [] [omd_node omd]
  and element_node = function
    | Omd.H1 omd -> h1 [] [omd_node omd]
    | H2 omd -> h2 [] [omd_node omd]
    | H3 omd -> h3 [] [omd_node omd]
    | H4 omd -> h4 [] [omd_node omd]
    | H5 omd -> h5 [] [omd_node omd]
    | H6 omd -> h6 [] [omd_node omd]
    | Paragraph omd -> p [] [omd_node omd]
    | Text str -> txt "%s" str
    | Emph omd -> em [] [omd_node omd]
    | Bold omd -> b [] [omd_node omd]
    | Ul omds | Ulp omds -> ul [] @@ List.map item omds
    | Ol omds | Olp omds -> ol [] @@ List.map item omds
    | Code (cls, str) -> code [class_ "%s" cls] [txt "%s" str]
    | Code_block (cls, str) ->
      pre [class_ "%s" cls] [code [class_ "%s" cls] [txt "%s" str]]
    | Br -> br []
    | Hr -> hr []
    | NL -> txt "\n"
    | Url (hre, omd, titl) ->
      a
        [ href "%s" hre;
          target "_blank";
          class_ "after:content-['_↗️']";
          title "%s" titl ]
        [omd_node omd]
    | Html ("details", attrs, omd) ->
      details (List.map omd_attr attrs) [omd_node omd]
    | Html ("summary", attrs, omd) ->
      summary (List.map omd_attr attrs) [omd_node omd]
    | Html_block ("details", attrs, omd) ->
      details (List.map omd_attr attrs) [omd_node omd]
    | Html_block ("summary", attrs, omd) ->
      summary (List.map omd_attr attrs) [omd_node omd]
    | Ref (_, _, _, _)
    | Img_ref (_, _, _, _)
    | Html (_, _, _)
    | Html_block (_, _, _)
    | X _ -> Tag.null []
    | Html_comment str -> comment str
    | Raw str -> txt ~raw:true "%s" str
    | Raw_block str -> pre [] [txt ~raw:true "%s" str]
    | Blockquote omd -> blockquote [] [omd_node omd]
    | Img (al, sr, titl) -> img [alt "%s" al; src "%s" sr; title "%s" titl]The entrypoint of the functionality is the omd_node function, which converts from the Omd.t value which can be obtained by, for example, parsing Markdown with the Omd.of_string function, to a type-safe node value.
In the element_node function we traverse the Markdown structure and convert it into specific nodes–tags, comments, etc.. Text is escaped as appropriate and some specific conversions are handled specially:
<details> and <summary> HTML tags, but no others.This is just an example, but it shows the idea that we can take various formats and interop with them using type-sdfe HTML generated by dream-html.