diff --git a/example/7-template/README.md b/example/7-template/README.md index 8074baea..780de8f8 100644 --- a/example/7-template/README.md +++ b/example/7-template/README.md @@ -149,6 +149,10 @@ and not supported by Dream. OCaml's type system to prevent emitting many kinds of invalid HTML. - [**`r-tyxml`**](../r-tyxml#files) if you are using Reason. You can use TyXML with JSX syntax server-side! +- [**`w-dream-html`**](../w-dream-html#files) shows how to use + [dream-html](https://github.com/yawaramin/dream-html), another alternative + library for generating HTML from OCaml, which is more closely integrated with + Dream. - [**`w-template-stream`**](../w-template-stream#files) streams templates to responses, instead of building up complete response strings. diff --git a/example/README.md b/example/README.md index f38fba43..0da93f97 100644 --- a/example/README.md +++ b/example/README.md @@ -128,6 +128,8 @@ if something is missing! reverse proxy. - [**`w-tyxml`**](w-tyxml#files)  —  uses TyXML for type-checked HTML templating. +- [**`w-dream-html`**](../w-dream-html#files)  —  uses + dream-html for convenient HTML generation from OCaml. - [**`w-long-polling`**](w-long-polling#files)  —  old form of asynchronous communication without WebSockets. - [**`w-query`**](w-query#files)  —  reads URL query parameters. diff --git a/example/w-dream-html/README.md b/example/w-dream-html/README.md new file mode 100644 index 00000000..0e8411d8 --- /dev/null +++ b/example/w-dream-html/README.md @@ -0,0 +1,67 @@ +# `w-dream-html` + +
+ +[Dream-html](https://github.com/yawaramin/dream-html) can be used with Dream for +generating HTML. Dream-html is a library that offers functions for generating +HTML, SVG, and MathML, as well as out-of-the-box support for +[htmx](https://htmx.org/) attributes. It is closely integrated with Dream for +convenience. + +```ocaml +let greet who = + let open Dream_html in + let open HTML in + html [lang "en"] [ + head [] [ + title [] "Greeting"; + ]; + comment "Embedded in the HTML"; + body [] [ + h1 [] [txt "Good morning, %s!" who]; + ]; + ] + +let () = + Dream.run + @@ Dream.logger + @@ Dream.router [ + + Dream.get "/" + (fun _ -> Dream_html.respond (greet "world")); + + ] +``` + +
$ cd example/w-dream-html
+$ opam install --deps-only --yes .
+$ dune exec --root . ./main.exe
+ +Try it in the [playground](https://dream.as/w-dream-html). + +Some notes: + +- All text nodes and attributes are HTML-escaped by default for security, with + exceptions noted in the documentation +- All text nodes and attributes accept format strings for conveniently embedding + variables in the HTML +- Functions like `Dream_html.respond`, `Dream_html.send`, `Dream_html.csrf_tag` + provide convenient integration with Dream +- The `` prefix is automatically rendered before the `` tag +- The `SVG` and `MathML` modules provide their corresponding markup. The `Hx` + module provides htmx attributes. + +
+
+ +**See also:** + +- [**`7-template`**](../7-template#security) section *Security* on output + security. Dream-html escapes strings by default, just as the built-in templater + does. +- [**`w-tyxml`**](../w-tyxml#files) is a similar library that also generates + HTML, with different design tradeoffs. + +
+ +[Up to the example index](../#examples) diff --git a/example/w-dream-html/dune b/example/w-dream-html/dune new file mode 100644 index 00000000..cb50156f --- /dev/null +++ b/example/w-dream-html/dune @@ -0,0 +1,3 @@ +(executable + (name html) + (libraries dream-html)) diff --git a/example/w-dream-html/dune-project b/example/w-dream-html/dune-project new file mode 100644 index 00000000..929c696e --- /dev/null +++ b/example/w-dream-html/dune-project @@ -0,0 +1 @@ +(lang dune 2.0) diff --git a/example/w-dream-html/html.ml b/example/w-dream-html/html.ml new file mode 100644 index 00000000..1d3eea15 --- /dev/null +++ b/example/w-dream-html/html.ml @@ -0,0 +1,23 @@ +let greet who = + let open Dream_html in + let open HTML in + html [lang "en"] [ + head [] [ + title [] "Greeting"; + ]; + comment "Embedded in the HTML"; + body [] [ + h1 [] [txt "Good morning, %s!" who]; + ]; + ] + +let () = + Dream.run + @@ Dream.logger + @@ Dream.router [ + + Dream.get "/" + (fun _ -> Dream_html.respond (greet "world")); + + ] + diff --git a/example/w-dream-html/w-dream-html.opam b/example/w-dream-html/w-dream-html.opam new file mode 100644 index 00000000..29d5a730 --- /dev/null +++ b/example/w-dream-html/w-dream-html.opam @@ -0,0 +1,7 @@ +opam-version: "2.0" + +depends: [ + "ocaml" {>= "4.08.0"} + "dream-html" {>= "3.3.1"} + "dune" {>= "2.0.0"} +] diff --git a/example/z-playground/server/sync.sh b/example/z-playground/server/sync.sh index 3dce1b2b..12f1548c 100644 --- a/example/z-playground/server/sync.sh +++ b/example/z-playground/server/sync.sh @@ -52,6 +52,7 @@ example k-websocket example w-query example w-flash example w-tyxml +example w-dream-html example w-chat example w-graphql-subscription example w-long-polling