Pleased to announce the release of dream-html 3.5.2, which actually spawns a new package pure-html: pure-html 3.5.2 (latest) · OCaml Package
This package offers the same functionality as dream-html, except without a Dream dependency, so you can use whatever web server you like, or even use it for other applications than web servers. It works exactly the same way as dream-html, except the top-level module is Pure_html
:
open Pure_html
open HTML
let content = article [] [
p [] [txt "Header"];
p [] [txt "Body"];
]
pure-html has a runtime dependency only on the uri
package.
11 Likes
Thanks again @yawaramin for doing this! Much appreciated.
1 Like
[ANN] dream-html & pure-html 3.6.0
Hello, I am happy to announce the following changes:
- Added some htmx attributes that had been omitted. Now as far as I can tell we have complete coverage of all core attributes, additional attributes, and those used by core extensions.
- Add a
?header:bool
optional parameter to to_xml
and pp_xml
functions to conveniently render the XML header as part of the output.
3 Likes
[ANN] dream-html & pure-html 3.6.1, 3.6.2
A double announcement:
3.6.1: when in XML rendering mode, correctly render empty-value attributes as having an empty string value. Thanks to @jonsterling !
3.6.2: automatically switch to XML rendering mode when rendering SVG and MathML tags inside HTML rendering mode.
1 Like
[ANN] dream-html 3.7.0
Happy to announce the addition of a helper module for typed form decoding functionality. See the docs here: Form (dream-html.Dream_html.Form)
An example:
type user = { name : string; age : int option }
open Dream_html.Form
let user_form =
let+ name = required string "name"
and+ age = optional int "age" in
{ name; age }
let dream_form = ["age", "42"; "name", "Bob"]
let user_result = validate user_form dream_form
(* => Ok { name = "Bob"; age = Some 42 } *)
let error_result = validate user_form ["age", "none"]
(* => Error [("age", "error.expected.int"); ("name", "error.required")] *)
Astute readers may observe that this provides some convenience functionality beyond what Dream itself offers; to validate the above form and get a complete set of field validation errors using only Dream you would do something like:
let user_result = match dream_form with
| ["age", age; "name", name] ->
(match int_of_string age with
| age -> Ok { name; age = Some age }
| exception Failure _ -> Error ["age", "error.expected.int"])
| ["name", name] -> Ok { name; age = None }
| ["age", age] ->
(match int_of_string age with
| age -> Error ["name", "error.required"]
| exception Failure _ -> Error ["age", "error.expected.int"; "name", "error.required"])
| _ -> Error ["name", "error.required"]
And this is a form with only two fields. You can imagine how convoluted the logic would be for more complex forms. Of course, you might just decide to use List.assoc_opt
and build up the validation errors, but even that can get tricky. So if you are making heavy use of HTML forms, a helper module that takes care of all these validation details can be very useful. Enjoy!
4 Likes
[ANN] dream-html 3.8.0
Happy to announce some added power to the form decoding functionality. Three main things:
- Added Dream_html.form and query helper functions to wrap extracting the data directly from the Dream request and decoding it correspondingly from the body or query.
- Added the (monadic) chaining operator Dream_html.Form.( let* ) and ok and error helpers to allow sophisticated sequential decoding where decoding of some fields depend on others.
- Added optional parameters to constrain typed decoding of values eg
int ~min:0
will succeed the decode if the value is an integer and at least 0. Also added unix_tm type decoder to decode timestamps into Unix.tm
structs (not timezone-aware).
The last example on the page shows a fairly sophisticated form decoder which requires an id
field and one or more of the fields days
, weeks
, months
, and years
, and fails if at least one is not provided.
Enjoy
2 Likes