use crate::html::Render; use crate::html::boxed_vec; use crate::html::elements::{Anchor, Image, Link, Paragraph}; use crate::html::layouts::Division; pub(crate) struct Page { title: String, head: Vec>, body: Vec>, } impl Render for Page { fn render(&self) -> String { format!( "\ {} {} {} ", self.title, self.head.render(), self.body.render() ) } } impl Page { pub(crate) fn builder() -> PageBuilder { PageBuilder::new() } 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)); } } pub(crate) struct PageBuilder { title: Option, head: Option>>, body: Option>>, } impl PageBuilder { pub(crate) fn new() -> Self { Self { title: None, head: None, body: None, } } pub(crate) fn title(self, title: T) -> Self where T: Into, { Self { title: Some(title.into()), ..self } } pub(crate) fn head(self, head: Vec>) -> Self { Self { head: Some(head), ..self } } pub(crate) fn body(self, body: Vec>) -> Self { Self { body: Some(body), ..self } } pub(crate) fn build(self) -> Page { let title = self.title.unwrap_or(String::new()); let head = self.head.unwrap_or(Vec::new()); let body = self.body.unwrap_or(Vec::new()); Page { title, head, body } } } pub(crate) struct BasePage { page: Page, } impl BasePage { pub(crate) fn builder() -> BasePageBuilder { BasePageBuilder::new() } pub(crate) fn append_element_to_head(&mut self, element: impl Render + 'static) { self.page.append_element_to_head(element); } pub(crate) fn append_element_to_body(&mut self, element: impl Render + 'static) { self.page.append_element_to_body(element); } } impl Render for BasePage { fn render(&self) -> String { self.page.render() } } pub(crate) struct BasePageBuilder { title: Option, head: Option>>, body: Option>>, } impl BasePageBuilder { pub(crate) fn new() -> Self { Self { title: None, head: None, body: None, } } pub(crate) fn title(self, title: T) -> Self where T: Into, { Self { title: Some(title.into()), ..self } } pub(crate) fn head(self, head: Vec>) -> Self { Self { head: Some(head), ..self } } pub(crate) fn body(self, body: Vec>) -> Self { Self { body: Some(body), ..self } } pub(crate) fn build(self) -> BasePage { let title = self.title.unwrap_or(String::new()); let head = self.head.unwrap_or(Vec::new()); let body = self.body.unwrap_or(Vec::new()); let name = Paragraph::builder() .id("name") .classes(vec!["name"]) .text("AINDUSTRIES") .build(); let home = Anchor::builder() .id("home") .classes(vec!["nav-button"]) .href("/") .text("Home") .build(); let projects = Anchor::builder() .id("projects") .classes(vec!["nav-button"]) .href("/projects") .text("Projects") .build(); let music = Anchor::builder() .id("music") .classes(vec!["nav-button"]) .href("/music") .text("Music") .build(); let buttons = Division::builder() .classes(vec!["nav-buttons"]) .elements(boxed_vec![home, projects, music]) .build(); let header = Division::builder() .id("header") .classes(vec!["header"]) .elements(boxed_vec![name, buttons]) .build(); // background let image = Image::builder() .id("background") .classes(vec!["background"]) .src("/static/img/background.png") .build(); // css let base = Link::builder() .rel("stylesheet") .href("/static/css/base.css") .build(); let mut final_head = boxed_vec![base]; final_head.extend(head); let mut final_body = boxed_vec![image, header]; final_body.extend(body); let page = Page::builder() .title(title) .head(final_head) .body(final_body) .build(); BasePage { page } } }