-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHtml.ml
130 lines (107 loc) · 2.36 KB
/
Html.ml
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
(*
Module providing HTML generation functionality.
*)
open ExtBase
(*
We use a separate type to represent HTML strings.
This helps us prevent escaping the same string twice.
*)
type t = Html of string
let to_string (Html s) =
s
(*
Turns an arbitrary string into valid HTML.
*)
let escape_string (string : string) : t =
let escape_char (char : char) : string =
match char with
| '<' -> "<"
| '>' -> ">"
| '&' -> "&"
| ' ' -> " "
| _ -> String.make 1 char
in
let chars = String.to_list string
in
let escaped = List.map ~f:escape_char chars
in
Html (String.concat ~sep:"" escaped)
(*
<ul>
<li>item 1</li>
<li>item 2</li>
...
<li>item N</li>
</ul>
*)
let unordered_list (items : t list) : t =
let html_items : string =
let html_item (Html item) : string =
Printf.sprintf "<li>%s</li>" item
in
String.concat ~sep:"" @@ List.map ~f:html_item items
in
Html (Printf.sprintf "<ul>%s</ul>" html_items)
(*
<tag attr1="value1" attr2="value2">
child
</tag>
*)
let element
(tag : string )
?(attributes : (string * string) list = [])
(child : t ) : t
=
let attributes' =
let format_attribute name value =
Printf.sprintf {| %s="%s"|} name value
in
String.concat @@ List.map ~f:(Fn.uncurry format_attribute) attributes
in
Html (
Printf.sprintf
"<%s%s>%s</%s>"
tag
attributes'
(to_string child)
tag
)
(*
<span class="class_name">
child
</span>
*)
let span
?(class_name : string option)
(child : t ) : t
=
let attributes =
match class_name with
| None -> []
| Some class_name -> [("class", class_name)]
in
element "span" ~attributes child
(*
<div class="class_name">
child
</div>
*)
let div
?(class_name : string option)
(child : t ) : t
=
let attributes =
match class_name with
| None -> []
| Some class_name -> [("class", class_name)]
in
element "div" ~attributes child
(*
Concatenates html documents into one.
*)
let concat (ts : t list) : t =
Html (String.concat @@ List.map ~f:to_string ts)
let string (string : string) : t =
escape_string string
let break : t =
Html "<br>"