fun_html/
elt.rs

1//! Common HTML elements
2//!
3//! Note that you may create your own element with [`Element::new`] or [`Element::new_void`]
4//!
5//! It is also possible to inline raw HTML with [`raw`] and [`raw_unsafe`]
6
7use alloc::{borrow::Cow, string::String};
8
9use crate::{
10    attr::{content, href, name, rel},
11    Attribute, Element, ElementInner,
12};
13
14/// Renders nothing. Useful fo conditional rendering.
15///
16/// # Example
17///
18/// ```
19/// use fun_html::{Element, elt::{text, none}};
20///
21/// let say_hello = true;
22/// let element: Element = if say_hello {
23///   text("Hello")
24/// } else {
25///   none()
26/// };
27/// ```
28pub fn none() -> Element {
29    Element(ElementInner::None)
30}
31
32/// `<div>`
33pub fn div(
34    attributes: impl IntoIterator<Item = Attribute>,
35    children: impl IntoIterator<Item = Element>,
36) -> Element {
37    Element::new("div", attributes, children)
38}
39
40/// `<head>`
41pub fn head(
42    attributes: impl IntoIterator<Item = Attribute>,
43    children: impl IntoIterator<Item = Element>,
44) -> Element {
45    Element::new("head", attributes, children)
46}
47
48/// `<legend>`
49pub fn legend(
50    attributes: impl IntoIterator<Item = Attribute>,
51    children: impl IntoIterator<Item = Element>,
52) -> Element {
53    Element::new("legend", attributes, children)
54}
55
56/// `<meta>`
57pub fn meta(attributes: impl IntoIterator<Item = Attribute>) -> Element {
58    Element::new_void("meta", attributes)
59}
60
61/// `<meta charset="UFT-8">`
62#[deprecated(since = "1.5.0", note = "renamed to 'meta_charset_utf8'")]
63pub fn meta_charset_utf_8() -> Element {
64    raw("<meta charset=\"UTF-8\">")
65}
66
67/// `<meta charset="UFT-8">`
68pub fn meta_charset_utf8() -> Element {
69    raw("<meta charset=\"UTF-8\">")
70}
71
72/// `<meta name="viewport" content="width=device-width, initial-scale=1.0">`
73pub fn meta_viewport() -> Element {
74    raw("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">")
75}
76
77/// `<meta name="color-scheme content="{scheme}">
78pub fn meta_color_scheme(scheme: impl Into<Cow<'static, str>>) -> Element {
79    meta([name("color-scheme"), content(scheme)])
80}
81
82/// `<link>`
83pub fn link(attributes: impl IntoIterator<Item = Attribute>) -> Element {
84    Element::new_void("link", attributes)
85}
86
87/// `<link rel="stylesheet" href="{url}">`
88pub fn link_stylesheet(url: impl Into<Cow<'static, str>>) -> Element {
89    link([rel("stylesheet"), href(url)])
90}
91
92/// `<script>`
93pub fn script(attributes: impl IntoIterator<Item = Attribute>, content: &'static str) -> Element {
94    Element::new(
95        "script",
96        attributes,
97        [Element(ElementInner::Script(content.into()))],
98    )
99}
100
101/// `<script>`
102pub fn script_empty(attributes: impl IntoIterator<Item = Attribute>) -> Element {
103    Element::new("script", attributes, [])
104}
105
106/// `<title>`
107pub fn title(
108    attributes: impl IntoIterator<Item = Attribute>,
109    text: impl Into<Cow<'static, str>>,
110) -> Element {
111    Element::new("title", attributes, [text.into().into()])
112}
113
114/// `<body>`
115pub fn body(
116    attributes: impl IntoIterator<Item = Attribute>,
117    children: impl IntoIterator<Item = Element>,
118) -> Element {
119    Element::new("body", attributes, children)
120}
121
122/// `<hgroup>`
123pub fn hgroup(
124    attributes: impl IntoIterator<Item = Attribute>,
125    children: impl IntoIterator<Item = Element>,
126) -> Element {
127    Element::new("hgroup", attributes, children)
128}
129
130/// `<h1>`
131pub fn h1(
132    attributes: impl IntoIterator<Item = Attribute>,
133    children: impl IntoIterator<Item = Element>,
134) -> Element {
135    Element::new("h1", attributes, children)
136}
137
138/// `<h2>`
139pub fn h2(
140    attributes: impl IntoIterator<Item = Attribute>,
141    children: impl IntoIterator<Item = Element>,
142) -> Element {
143    Element::new("h2", attributes, children)
144}
145
146/// `<h3>`
147pub fn h3(
148    attributes: impl IntoIterator<Item = Attribute>,
149    children: impl IntoIterator<Item = Element>,
150) -> Element {
151    Element::new("h3", attributes, children)
152}
153
154/// `<h4>`
155pub fn h4(
156    attributes: impl IntoIterator<Item = Attribute>,
157    children: impl IntoIterator<Item = Element>,
158) -> Element {
159    Element::new("h4", attributes, children)
160}
161
162/// `<h5>`
163pub fn h5(
164    attributes: impl IntoIterator<Item = Attribute>,
165    children: impl IntoIterator<Item = Element>,
166) -> Element {
167    Element::new("h5", attributes, children)
168}
169
170/// `<h6>`
171pub fn h6(
172    attributes: impl IntoIterator<Item = Attribute>,
173    children: impl IntoIterator<Item = Element>,
174) -> Element {
175    Element::new("h6", attributes, children)
176}
177
178/// `<p>`
179pub fn p(
180    attributes: impl IntoIterator<Item = Attribute>,
181    children: impl IntoIterator<Item = Element>,
182) -> Element {
183    Element::new("p", attributes, children)
184}
185
186/// `<br>`
187pub fn br(attributes: impl IntoIterator<Item = Attribute>) -> Element {
188    Element::new_void("br", attributes)
189}
190
191/// `<hr>`
192pub fn hr(attributes: impl IntoIterator<Item = Attribute>) -> Element {
193    Element::new_void("hr", attributes)
194}
195
196/// `<small>`
197pub fn small(
198    attributes: impl IntoIterator<Item = Attribute>,
199    children: impl IntoIterator<Item = Element>,
200) -> Element {
201    Element::new("small", attributes, children)
202}
203
204/// `<span>`
205pub fn span(
206    attributes: impl IntoIterator<Item = Attribute>,
207    children: impl IntoIterator<Item = Element>,
208) -> Element {
209    Element::new("span", attributes, children)
210}
211
212/// `<table>`
213pub fn table(
214    attributes: impl IntoIterator<Item = Attribute>,
215    children: impl IntoIterator<Item = Element>,
216) -> Element {
217    Element::new("table", attributes, children)
218}
219
220/// `<tr>`
221pub fn tr(
222    attributes: impl IntoIterator<Item = Attribute>,
223    children: impl IntoIterator<Item = Element>,
224) -> Element {
225    Element::new("tr", attributes, children)
226}
227
228/// `<td>`
229pub fn td(
230    attdibutes: impl IntoIterator<Item = Attribute>,
231    children: impl IntoIterator<Item = Element>,
232) -> Element {
233    Element::new("td", attdibutes, children)
234}
235
236/// `<th>`
237pub fn th(
238    attdibutes: impl IntoIterator<Item = Attribute>,
239    children: impl IntoIterator<Item = Element>,
240) -> Element {
241    Element::new("th", attdibutes, children)
242}
243
244/// `<thead>`
245pub fn thead(
246    attributes: impl IntoIterator<Item = Attribute>,
247    children: impl IntoIterator<Item = Element>,
248) -> Element {
249    Element::new("thead", attributes, children)
250}
251
252/// `<tbody>`
253pub fn tbody(
254    attributes: impl IntoIterator<Item = Attribute>,
255    children: impl IntoIterator<Item = Element>,
256) -> Element {
257    Element::new("tbody", attributes, children)
258}
259
260/// `<tfoot>`
261pub fn tfoot(
262    attributes: impl IntoIterator<Item = Attribute>,
263    children: impl IntoIterator<Item = Element>,
264) -> Element {
265    Element::new("tfoot", attributes, children)
266}
267
268/// `<section>`
269pub fn section(
270    attributes: impl IntoIterator<Item = Attribute>,
271    children: impl IntoIterator<Item = Element>,
272) -> Element {
273    Element::new("section", attributes, children)
274}
275
276/// `<article>`
277pub fn article(
278    attributes: impl IntoIterator<Item = Attribute>,
279    children: impl IntoIterator<Item = Element>,
280) -> Element {
281    Element::new("article", attributes, children)
282}
283
284/// `<header>`
285pub fn header(
286    attributes: impl IntoIterator<Item = Attribute>,
287    children: impl IntoIterator<Item = Element>,
288) -> Element {
289    Element::new("header", attributes, children)
290}
291
292/// `<main>`
293pub fn main(
294    attributes: impl IntoIterator<Item = Attribute>,
295    children: impl IntoIterator<Item = Element>,
296) -> Element {
297    Element::new("main", attributes, children)
298}
299
300/// `<footer>`
301pub fn footer(
302    attributes: impl IntoIterator<Item = Attribute>,
303    children: impl IntoIterator<Item = Element>,
304) -> Element {
305    Element::new("footer", attributes, children)
306}
307
308/// `<a>`
309pub fn a(
310    attributes: impl IntoIterator<Item = Attribute>,
311    children: impl IntoIterator<Item = Element>,
312) -> Element {
313    Element::new("a", attributes, children)
314}
315
316/// `<img>`
317pub fn img(attributes: impl IntoIterator<Item = Attribute>) -> Element {
318    Element::new_void("img", attributes)
319}
320
321/// `<ul>`
322pub fn ul(
323    attributes: impl IntoIterator<Item = Attribute>,
324    children: impl IntoIterator<Item = Element>,
325) -> Element {
326    Element::new("ul", attributes, children)
327}
328
329/// `<ol>`
330pub fn ol(
331    attributes: impl IntoIterator<Item = Attribute>,
332    children: impl IntoIterator<Item = Element>,
333) -> Element {
334    Element::new("ol", attributes, children)
335}
336
337/// `<li>`
338pub fn li(
339    attributes: impl IntoIterator<Item = Attribute>,
340    children: impl IntoIterator<Item = Element>,
341) -> Element {
342    Element::new("li", attributes, children)
343}
344
345/// `<form>`
346pub fn form(
347    attributes: impl IntoIterator<Item = Attribute>,
348    children: impl IntoIterator<Item = Element>,
349) -> Element {
350    Element::new("form", attributes, children)
351}
352
353/// `<fieldset>`
354pub fn fieldset(
355    attributes: impl IntoIterator<Item = Attribute>,
356    children: impl IntoIterator<Item = Element>,
357) -> Element {
358    Element::new("fieldset", attributes, children)
359}
360
361/// `<input>`
362pub fn input(attributes: impl IntoIterator<Item = Attribute>) -> Element {
363    Element::new_void("input", attributes)
364}
365
366/// `<textarea>`
367pub fn textarea(
368    attributes: impl IntoIterator<Item = Attribute>,
369    text: impl Into<Cow<'static, str>>,
370) -> Element {
371    Element::new("textarea", attributes, [text.into().into()])
372}
373
374/// `<select>`
375pub fn select(
376    attributes: impl IntoIterator<Item = Attribute>,
377    children: impl IntoIterator<Item = Element>,
378) -> Element {
379    Element::new("select", attributes, children)
380}
381
382/// `<option>`
383pub fn option(
384    attributes: impl IntoIterator<Item = Attribute>,
385    children: impl IntoIterator<Item = Element>,
386) -> Element {
387    Element::new("option", attributes, children)
388}
389
390/// `<button>`
391pub fn button(
392    attributes: impl IntoIterator<Item = Attribute>,
393    children: impl IntoIterator<Item = Element>,
394) -> Element {
395    Element::new("button", attributes, children)
396}
397
398/// `<label>`
399pub fn label(
400    attributes: impl IntoIterator<Item = Attribute>,
401    children: impl IntoIterator<Item = Element>,
402) -> Element {
403    Element::new("label", attributes, children)
404}
405
406/// HTML escaped text
407pub fn text(value: impl Into<Cow<'static, str>>) -> Element {
408    ElementInner::Text(value.into()).into()
409}
410
411/// Inline raw HTML without escaping
412///
413/// This function is considered safe because the HTML being inlined must be known at compile time
414///
415/// See [`raw_unsafe`] to inline HTML that is generated at runtime
416pub fn raw(html: &'static str) -> Element {
417    ElementInner::Raw(html.into()).into()
418}
419
420/// Inline raw HTML without escaping
421///
422/// This function **IS NOT SAFE** and should be avoided unless really necessary.
423/// Miss-use can lead to XSS vulnerability.
424///
425/// See [`raw`] to safely inline HTML that is known at compile time
426pub fn raw_unsafe(html: String) -> Element {
427    ElementInner::Raw(html.into()).into()
428}
429
430impl From<Cow<'static, str>> for Element {
431    fn from(value: Cow<'static, str>) -> Self {
432        text(value)
433    }
434}
435
436impl From<&'static str> for Element {
437    fn from(value: &'static str) -> Self {
438        text(value)
439    }
440}
441
442impl From<String> for Element {
443    fn from(value: String) -> Self {
444        text(value)
445    }
446}