-
Notifications
You must be signed in to change notification settings - Fork 0
/
html.gleam
359 lines (325 loc) · 11 KB
/
html.gleam
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
import html_dsl/types/attribute.{type Attribute, attribute_to_string}
import html_dsl/types/html/head.{type Head}
import html_dsl/utils/check.{illegal_string_check}
import gleam/io
import gleam/option.{type Option}
/// Exists to prevent strings from being passed to engines
///
/// Engines should require `Html` or `Component`
pub opaque type Html {
Html(String)
Component(String)
Nil
}
/// Exists to prevent strings from being passed to engines
pub opaque type Body {
Body(String)
}
/// Converts body to string
pub fn body_to_string(body: Body) -> String {
case body {
Body(content) -> content
}
}
/// Check Html enum
/// - `@param` html: The Html enum
/// - `@returns`: True if the Html enum is Html, False if it is Component
pub fn is_html(html: Html) -> Bool {
case html {
Html(_) -> True
_ -> False
}
}
/// Converts Html enum to a string
pub fn html_to_string(html: Html) -> String {
case html {
Html(content) -> content
Component(content) -> content
Nil -> ""
}
}
/// This creates a string that represents a div element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn div(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
// I'm too lazy, so I'm going to add id to the attributes list
let att_str = attribute_to_string(attributes)
"<div" <> att_str <> ">" <> inner <> "</div>"
}
/// This creates a string that represents an image element
/// - `@param` src: The source of the image
/// - `@param` alt: The alt text of the image
/// - `@param` attributes: The attributes of the element
/// - `@returns`: A string that represents the HTML element
pub fn img(
src src: String,
alt alt: String,
attributes attributes: Option(Attribute),
) -> String {
let att_str = attribute_to_string(attributes)
let src = illegal_string_check(src)
let alt = illegal_string_check(alt)
"<img src=\"" <> src <> "\" alt=\"" <> alt <> "\"" <> att_str <> "/>"
}
/// This creates a string that represents an anchor element
/// - `@param` href: The href of the anchor
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn a(
href href: String,
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
let href = illegal_string_check(href)
"<a href=\"" <> href <> "\"" <> att_str <> ">" <> inner <> "</a>"
}
/// This creates a string that represents an h1 element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn h1(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<h1" <> att_str <> ">" <> inner <> "</h1>"
}
/// This creates a string that represents an h2 element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn h2(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<h2" <> att_str <> ">" <> inner <> "</h2>"
}
/// This creates a string that represents an h3 element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn h3(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<h3" <> att_str <> ">" <> inner <> "</h3>"
}
/// This creates a string that represents an h4 element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn h4(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<h4" <> att_str <> ">" <> inner <> "</h4>"
}
/// This creates a string that represents an h5 element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn h5(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<h5" <> att_str <> ">" <> inner <> "</h5>"
}
/// This creates a string that represents an h6 element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn h6(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<h6" <> att_str <> ">" <> inner <> "</h6>"
}
/// This creates a string that represents a paragraph element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn p(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<p" <> att_str <> ">" <> inner <> "</p>"
}
/// This creates a string that represents a span element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn span(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<span" <> att_str <> ">" <> inner <> "</span>"
}
/// This creates a string that represents a break element
/// - `@returns`: A string that represents the HTML element
pub fn br() -> String {
"<br>"
}
/// This creates a string that represents a horizontal rule element
/// - `@returns`: A string that represents the HTML element
pub fn hr() -> String {
"<hr>"
}
/// This creates a string that represents the body of an HTML document
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn body(
attributes attributes: Option(Attribute),
inner inner: String,
) -> Body {
let att_str = attribute_to_string(attributes)
Body("<body" <> att_str <> ">" <> inner <> "</body>")
}
/// This force resolves a `Result(Html, String)` to `Html`
/// - `@param` result: The result to resolve
/// - `@returns`: The resolved `Html`
pub fn force(result: Result(Html, String)) -> Html {
case result {
Ok(html) -> html
Error(s) -> {
io.print(s)
Nil
}
}
}
/// This creates a string that represents an HTML document
/// - `@param` lang: The language of the document
/// - `@param` children: The children of the document
/// - `@returns`: A string that represents the HTML element
pub fn html(
lang lang: String,
head head: Head,
body body: Body,
) -> Result(Html, String) {
let lang = illegal_string_check(lang)
case head.resolve(head) {
Ok(head) -> {
Ok(Html(
"<!DOCTYPE html><html lang=\""
<> lang
<> "\">"
<> case head {
"" -> ""
_ -> head
}
<> body_to_string(body)
<> "</html>",
))
}
Error(s) -> {
Error("Error: `Head` cannot resolve -> " <> s)
}
}
}
/// This creates a string that represents a component
/// - `@param` content: The content of the component
/// - `@returns`: A Component
pub fn component(content: String) -> Html {
Component(content)
}
/// This creates a string that represents a header element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn header(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<header" <> att_str <> ">" <> inner <> "</header>"
}
/// This creates a string that represents a footer element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn footer(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<footer" <> att_str <> ">" <> inner <> "</footer>"
}
/// This creates a string that represents a nav element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn nav(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<nav" <> att_str <> ">" <> inner <> "</nav>"
}
/// This creates a string that represents a section element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn section(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<section" <> att_str <> ">" <> inner <> "</section>"
}
/// This creates a string that represents an article element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn article(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<article" <> att_str <> ">" <> inner <> "</article>"
}
/// This creates a string that represents an aside element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn aside(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<aside" <> att_str <> ">" <> inner <> "</aside>"
}
/// This creates a string that represents a main element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn main(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<main" <> att_str <> ">" <> inner <> "</main>"
}
/// This creates a string that represents a button element
/// - `@param` attributes: The attributes of the element
/// - `@param` inner: The child of the element
/// - `@returns`: A string that represents the HTML element
pub fn button(
attributes attributes: Option(Attribute),
inner inner: String,
) -> String {
let att_str = attribute_to_string(attributes)
"<button" <> att_str <> ">" <> inner <> "</button>"
}