Page
Library
Module
Module type
Parameter
Class
Class type
Source
Copyright 2023 Yawar Amin
This file is part of dream-html.
dream-html is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
dream-html is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with dream-html. If not, see https://www.gnu.org/licenses/.
An HTML library that is closely integrated with Dream. Most HTML elements and attributes from the Mozilla Developer Network references are now implemented. I have deliberately left out almost all non-standard or deprecated tags/attributes. Also, supporting CSS is out of scope for this library. However, I have included the htmx attributes as I am personally using them.
let page req =
let open Dream_html in
let open HTML in
html [lang "en"] [
head [] [
title [] "Dream-html" ];
body [] [
h1 [] [txt "Dream-html"];
p [] [txt "Is cool!"];
form [method_ `POST; action "/feedback"] [
(* Integrated with Dream's CSRF token generation *)
csrf_tag req;
label [for_ "what-you-think"] [txt "Tell us what you think!"];
input [name "what-you-think"; id "what-you-think"];
input [type_ "submit"; value "Send"] ] ] ]
(* Integrated with Dream response *)
let handler req = Dream_html.respond (page req)
Attribute and text values are escaped using rules very similar to standards- compliant web browsers:
utop # open Dream_html;;
utop # open HTML;;
utop # #install_printer pp;;
utop # let user_input = "<script>alert('You have been pwned')</script>";;
val user_input : string = "<script>alert('You have been pwned')</script>"
utop # p [] [txt "%s" user_input];;
- : node = <p><script>alert('You have been pwned')</script></p>
utop # div [title_ {|"%s|} user_input] [];;
- : node = <div title=""<script>alert('You have been pwned')</script>"></div>
Make sure your local copy of the opam repository is up-to-date first:
opam update
opam install dream-html
A convenience is provided to respond with an HTML node from a handler:
Dream_html.respond greeting
You can compose multiple HTML nodes together into a single node without an extra DOM node, like React fragments:
let view = null [p [] [txt "Hello"]; p [] [txt "World"]]
You can do string interpolation using the txt
node constructor and of any attribute which takes a string value:
let greet name = p [id "greet-%s" name] [txt "Hello, %s!" name]
You can conditionally render an attribute, and void elements are statically enforced as childless:
let entry =
input
[ (if should_focus then autofocus else null_);
id "email";
name "email";
value "Email address" ]
You can also embed HTML comments in the generated document:
div [] [comment "TODO: xyz."; p [] [txt "Hello!"]]
$ utop
utop # #require "dream-html";;
utop # open Dream_html;;
utop # open HTML;;
utop # #install_printer pp;;
utop # p [class_ "hello"] [txt "world"];;
- : node = <p class="hello">world</p>
Run the test and print out diff if it fails:
dune runtest # Will also exit 1 on failure
Set the new version of the output as correct:
dune promote
Surface design obviously lifted straight from elm-html.
Similar to Webs as mentioned earlier (it turns out there are only a limited number of ways to do this kind of library).
Implementation inspired by both elm-html and Scalatags.