I am very happy to announce the release of ocaml-embedded-templates.
This is a tool similar to camlmix, but camlmix was not updated for 7 years, and there is no easy way to handle a lot of templates (my command takes a directory as an argument and generate an ocaml module by going through the directory recursively)
I also choosed to use a syntax similar to EJS, and there is a ppx for inline EML.
This looks very interesting, Iβll try it out. Iβm writing a web framework and need a good view compiler. Currently Iβm using functions as views, e.g.
let view_article id name p =
p {|<article id="|};
p id;
p {|"><h2>|};
p name;
p {|</h2></article>|}
Obviously, this is sub-optimal.
My question is, how close is ocaml-embedded-templates output to my view functions? I.e., will a template like:
<%# id name %>
<article id="<%-id%>"><h2><%-name%></h2></article>
I will not really do that.
Your function/view is of type string -> string -> (string -> unit) -> unit.
The function generated by EML will be of type string -> string -> string.
However I see the benefits of your approach, and I think it might be a good idea to add this, maybe as an option to EML, or maybe p could be an optionnal parameter to the function. It would be really easy to implement and provide a lot of benefits (less allocations I guess, depending on p's value).
Dont you think having type (string -> unit) -> string -> string -> unit would be better though ? This would allow to curry the template by the output function you like.
Exactly, the idea is to avoid allocations, e.g. imagine that p is print_string. In my web framework I have an API for responding with a view, Response.of_view (view_article id name). Keeping the p as the final parameter allows me to partially apply all the other parameters of the view and always pass a ((string -> unit) -> unit) to Response.of_view.
To be honest, this approach is not completely my idea, I saw ECaml doing something very close, but didnβt use ECaml itself because it is GPL licensed (although thatβs probably not a great reason).
EDIT: but I will play around with your repo, see how it works. Thanks for publishing!
Oh Tyxml is quite nice, I did not knew it could do that.
I have pushed a commit that allow you to do exactly what you wanted, I also modified the exemple to use the new option, tell me if you think itβs useful.
For now I want an unopinionated templating language that can output anything from HTML to JSON to CSV, etc., but Tyxml is a very cool technology, I will take another look at it.
How can I test this in the ocaml repl or utop? Iβve tried:
# #require "tyxml-jsx";;
# let%html view_article id name p =
"<article id="id"><h2>"name"</h2></article>";;
Error: Uninterpreted extension 'html'.
# #ppx "/Users/boris/.opam/ocsi/lib/tyxml-jsx/./ppx.exe";;
# let%html view_article id name p =
"<article id="id"><h2>"name"</h2></article>";;[%%html
let view_article id name p =
"<article id=" id "><h2>" name "</h2></article>"]
File "/var/folders/kl/7z2_bknj4ynch1dlb6d8w5jm0000gn/T/camlppx94864b", line 1:
Error: I can't decide whether /var/folders/kl/7z2_bknj4ynch1dlb6d8w5jm0# let%html view_article id name p =
"<article id="id"><h2>"name"</h2></article>";;
Error: Error while running external preprocessor
No need to mess with utopβs #ppx directives, it is set up automatically when you require the ppx library (but fwiw, you were trying to wire in the jsx ppx, which is not what Drupβs example is using).