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.
Webs_html
is most similar but I wanted to fine-tune a few things and take advantage of close Dream integration.let page req =
let open Dream_html in
let open Tag in
let open Attr in
html [lang "en"] [
head [] [
(* Need module prefix because conflicts with title attribute *)
Tag.title [] "Dream-html" ];
body [] [
h1 [] [txt "Dream-html"];
p [] [txt "Is cool!"];
(* Need module prefix because conflicts with form attribute *)
Tag.form [method_ `POST; action "/feedback"] [
(* Integrated with Dream's CSRF token generation *)
csrf_tag req;
(* Need module prefix because conflicts with label attribute *)
Tag.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 Dream.html_escape
:
utop # open Dream_html;;
utop # let user_input = "<script>alert('You have been pwned')</script>";;
utop # open Tag;;
utop # let safe = p [] [txt "%s" user_input];;
utop # to_string safe;;
- : string =
"<p><script>alert('You have been pwned')</script></p>"
This package is not published on opam, so you can add it as a pinned package. E.g.
opam pin add dream-html git+https://github.com/yawaramin/dream-html
If you are using a dune-project
file to declare your dependencies, you can add the pin to your <package>.opam.template
file:
pin-depends: [
["dream-html.dev" "git+https://github.com/yawaramin/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 = Tag.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 Tag;;
utop # open Attr;;
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.