Load tyxml and the tyxml syntax extension.
In [1]:
#require "tyxml,iocaml-kernel.notebook"
In [2]:
#require "tyxml.syntax"
Define a function which takes a list of expanded tyxml html quotations and displays them.
In [3]:
(* setup pa_tyxml so we can write html quotations *)
let html q =
Html5.P.print_list ~output:(output_string Iocaml.mime) q;
Iocaml.send_mime "text/html"
module Html5 = Html5.M
Out[3]:
Out[3]:
Simple HTML example.
In [4]:
html [
<< <h1> hello </h1> >>;
<< <p> world </p> >>
]
Out[4]:
Javascript example. Load Chart.js and display a line chart with randomly generated data. Note that the javascript is embedded into the notebook and will be run when it is (re)loaded. If this causes an exception during loading the notebook will fail to start the kernel.
In [5]:
let random_data () =
let a = Array.init 7 (fun _ -> Random.int 100) in
List.fold_left (fun s x ->
let x = string_of_int x in
if s="" then x else s ^ "," ^ x) "" (Array.to_list a)
;;
let run () = html [
<< <canvas id="myChart" width="400" height="400"/> >>;
<< <script>
$$.getScript("https://rawgit.com/nnnick/Chart.js/master/Chart.js", function () {
var ctx = document.getElementById("myChart").getContext("2d");
var data = {
labels : ["January","February","March","April","May","June","July"],
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
pointColor : "rgba(220,220,220,1)",
pointStrokeColor : "#fff",
data : [$str:random_data()$]
},
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,1)",
pointColor : "rgba(151,187,205,1)",
pointStrokeColor : "#fff",
data : [$str:random_data()$]
}
]
}
new Chart(ctx).Line(data);
})
</script> >>;
]
Out[5]:
Out[5]:
In [6]:
run ()
Out[6]:
Here's a programatic example of SVG generation (because I cannot get the syntax extension to work).
In [7]:
let svg q =
Svg.P.print_list ~output:(output_string Iocaml.mime) q;
Iocaml.send_mime "text/html"
Out[7]:
In [8]:
let d = (Svg.M.(
svg ~a:[a_width (100.,None); a_height (100.,None)]
[circle ~a:[a_r (40.,None); a_cx (50.,None); a_cy (50.,None) ]
[]
]))
Out[8]:
In [9]:
Svg.P.print_list ~output:print_string [d]
Out[9]:
In [11]:
svg [d]
Out[11]:
Out[11]:
_I believe there is a bug with patyxml (2.2.0) for svg output. This is a test that works with a fix provided upstream.
In [12]:
svg (let module Svg = Svg.M in [ <:svg< <svg width="100" height="100"><circle r="40" cx="50" cy="50" /></svg> >> ])
Out[12]:
IPython has the ability to print a rich representation of the output value returned by a cell. We can do something similar by subverting the OCaml #install_printer
directive.
In [13]:
let html_printer_list fmt t = (html t; Format.fprintf fmt "<html>"; ())
let html_printer fmt x = html_printer_list fmt [x]
Out[13]:
Out[13]:
In [14]:
#install_printer html_printer;;
#install_printer html_printer_list;;
In [15]:
let _ = << <b> automatically printed </b> >>
Out[15]:
The TyXML syntax extension does not allow quotations at the expression level so we need to wrap it with the let _
.
The next example is a html table printer for some simple types with a bit of control over formatting.
In [16]:
type html_table =
| String_list of int * string list
| String_array of int * string array
| Int_list of int * int list
| Int_array of int * int array
let rec html_table data =
let rec f width n row str =
match str with
| [] -> if row=[] then [] else [List.rev row]
| h::t ->
if n=width then List.rev row :: f width 0 [] str
else f width (n+1) (h::row) t
in
let print l =
let row = List.map (fun x -> << <td>$str:x$</td> >>) in
let rows = List.map (fun x -> << <tr>$list:row x$</tr> >>) in
<< <table> $list:rows l$ </table> >>
in
match data with
| String_list(w,l) -> print (f w 0 [] l)
| String_array(w,l) -> html_table (String_list(w, Array.to_list l))
| Int_list(w,l) -> html_table (String_list(w, List.map string_of_int l))
| Int_array(w,l) -> html_table (Int_list(w, Array.to_list l))
let html_table_printer fmt x = (html [(html_table x)]; Format.fprintf fmt "<table>"; ());;
#install_printer html_table_printer;;
Out[16]:
Out[16]:
Out[16]:
In [17]:
String_list(2, [ "john"; "smith"; "joe"; "blogs" ])
Out[17]:
In [18]:
let data = Array.init 21 (fun i -> i) in
Array.init 3(fun i -> Int_array((i+1)*3,data))
Out[18]: