html_pipe/
lib.rs

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}