93 lines
1.8 KiB
Rust
93 lines
1.8 KiB
Rust
pub(crate) mod elements;
|
|
|
|
pub(crate) trait Render {
|
|
fn render(&self) -> String;
|
|
}
|
|
|
|
pub(crate) struct Page {
|
|
title: String,
|
|
head: Vec<Box<dyn Render>>,
|
|
body: Vec<Box<dyn Render>>,
|
|
}
|
|
|
|
pub(crate) struct PageBuilder {
|
|
title: Option<String>,
|
|
head: Option<Vec<Box<dyn Render>>>
|
|
body: Option<Vec<Box<dyn Render>>>
|
|
}
|
|
|
|
impl PageBuilder {
|
|
pub(crate) fn new() -> Self {
|
|
Self {
|
|
title: None,
|
|
head: None,
|
|
body: None,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn title<T>(mut self, title: T)
|
|
where T: Into<String>
|
|
{
|
|
self.title = Some(title.into());
|
|
}
|
|
}
|
|
|
|
impl Render for Vec<Box<dyn Render>> {
|
|
fn render(&self) -> String {
|
|
let mut result = String::new();
|
|
for element in self {
|
|
let render = element.render();
|
|
result.push_str(&render);
|
|
}
|
|
result
|
|
}
|
|
}
|
|
|
|
impl Render for Page {
|
|
fn render(&self) -> String {
|
|
format!(
|
|
"\
|
|
<!DOCTYPE html>
|
|
<html lang=\"en\">
|
|
<head>
|
|
<meta charset=\"UTF-8\">
|
|
<title>{}</title>
|
|
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />
|
|
{}
|
|
</head>
|
|
<body>
|
|
{}
|
|
</body>
|
|
</html>",
|
|
self.title,
|
|
self.head.render(),
|
|
self.body.render()
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Page {
|
|
pub(crate) fn builder() -> PageBuilder {
|
|
PageBuilder::new()
|
|
}
|
|
|
|
pub(crate) fn new<T>(title: T) -> Self
|
|
where
|
|
T: Into<String>,
|
|
{
|
|
Page {
|
|
title: title.into(),
|
|
head: vec![],
|
|
body: vec![],
|
|
}
|
|
}
|
|
|
|
pub(crate) fn append_element_to_body(&mut self, element: impl Render + 'static) {
|
|
self.body.push(Box::new(element));
|
|
}
|
|
|
|
pub(crate) fn append_element_to_head(&mut self, element: impl Render + 'static) {
|
|
self.head.push(Box::new(element));
|
|
}
|
|
}
|