1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
module Html : sig
type t
val string_of_list : t list -> string
type attr
val a_class : string list -> attr
val code : a:attr list -> t list -> t
val span : a:attr list -> t list -> t
val div : a:attr list -> t list -> t
val txt : string -> t
module Unsafe : sig
val data : string -> t
end
end = struct
type t =
| Raw of string
| Txt of string
| Concat of t list
let add_escape_string buf s =
(* https://discuss.ocaml.org/t/html-encoding-of-string/4289/4 *)
let add = Buffer.add_string buf in
let len = String.length s in
let max_idx = len - 1 in
let flush start i =
if start < len then Buffer.add_substring buf s start (i - start)
in
let rec loop start i =
if i > max_idx
then flush start i
else begin
match String.get s i with
| '&' -> escape "&" start i
| '<' -> escape "<" start i
| '>' -> escape ">" start i
| '\'' -> escape "'" start i
| '"' -> escape """ start i
| '@' -> escape "@" start i
| _ -> loop start (i + 1)
end
and escape amperstr start i =
flush start i ;
add amperstr ;
let next = i + 1 in
loop next next
in
loop 0 0
let to_string t =
let buf = Buffer.create 16 in
let rec go = function
| Raw s -> Buffer.add_string buf s
| Txt s -> add_escape_string buf s
| Concat xs -> List.iter go xs
in
go t ;
Buffer.contents buf
let string_of_list lst = to_string (Concat lst)
type attr = t
let a_class lst = Concat [ Raw "class=\""; Txt (String.concat " " lst); Raw "\"" ]
let attrs = function
| [] -> Concat []
| xs -> Concat (Raw " " :: xs)
let block name ~a body =
let name = Raw name in
Concat [ Raw "<"; name; attrs a; Raw ">"; Concat body; Raw "</"; name; Raw ">" ]
let code = block "code"
let span = block "span"
let div = block "span"
let txt s = Txt s
module Unsafe = struct
let data s = Raw s
end
end
|