1use std::fmt::Write;
2
3pub const DOCTYPE: &str = "<!DOCTYPE html>";
4pub type Buffer = String;
5pub type Result<T> = std::result::Result<T, std::fmt::Error>;
6
7pub fn node<'tag, Attrs, Children>(
8 tag: &'tag str,
9 attrs: Attrs,
10 children: Children,
11) -> impl FnOnce(&mut Buffer) -> Result<&mut Buffer> + 'tag
12where
13 Attrs: FnOnce(&mut Buffer) -> Result<&mut Buffer> + 'tag,
14 Children: FnOnce(&mut Buffer) -> Result<&mut Buffer> + 'tag,
15{
16 |buf| {
17 buf.push('<');
18 buf.push_str(tag);
19 attrs(buf)?;
20 buf.push('>');
21 children(buf)?;
22 buf.push_str("</");
23 buf.push_str(tag);
24 buf.push('>');
25 Ok(buf)
26 }
27}
28
29pub fn node_empty<'tag, Attrs>(
30 tag: &'tag str,
31 attrs: Attrs,
32) -> impl FnOnce(&mut Buffer) -> Result<&mut Buffer> + 'tag
33where
34 Attrs: FnOnce(&mut Buffer) -> Result<&mut Buffer> + 'tag,
35{
36 |buf| {
37 buf.push('<');
38 buf.push_str(tag);
39 attrs(buf)?;
40 buf.push_str("/>");
41 Ok(buf)
42 }
43}
44
45pub fn text(value: &str) -> impl FnOnce(&mut Buffer) -> Result<&mut Buffer> + '_ {
46 |buf| {
47 buf.push_str(value);
48 Ok(buf)
49 }
50}
51
52pub fn attr<'txt>(
53 key: &'txt str,
54 value: &'txt str,
55) -> impl FnOnce(&mut Buffer) -> Result<&mut Buffer> + 'txt {
56 move |buf| {
57 write!(buf, " {key}={value:?}")?;
58 Ok(buf)
59 }
60}
61
62pub fn noop(buf: &mut Buffer) -> Result<&mut Buffer> {
63 Ok(buf)
64}
65
66pub trait Component {
67 fn render<'b>(&self, buf: &'b mut Buffer) -> Result<&'b mut Buffer> {
68 Ok(buf)
69 }
70}