216 lines
5.2 KiB
Rust
216 lines
5.2 KiB
Rust
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<Box<dyn Render>>,
|
|
body: Vec<Box<dyn Render>>,
|
|
}
|
|
|
|
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 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<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>(self, title: T) -> Self
|
|
where
|
|
T: Into<String>,
|
|
{
|
|
Self {
|
|
title: Some(title.into()),
|
|
..self
|
|
}
|
|
}
|
|
|
|
pub(crate) fn head(self, head: Vec<Box<dyn Render>>) -> Self {
|
|
Self {
|
|
head: Some(head),
|
|
..self
|
|
}
|
|
}
|
|
|
|
pub(crate) fn body(self, body: Vec<Box<dyn Render>>) -> 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<String>,
|
|
head: Option<Vec<Box<dyn Render>>>,
|
|
body: Option<Vec<Box<dyn Render>>>,
|
|
}
|
|
|
|
impl BasePageBuilder {
|
|
pub(crate) fn new() -> Self {
|
|
Self {
|
|
title: None,
|
|
head: None,
|
|
body: None,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn title<T>(self, title: T) -> Self
|
|
where
|
|
T: Into<String>,
|
|
{
|
|
Self {
|
|
title: Some(title.into()),
|
|
..self
|
|
}
|
|
}
|
|
|
|
pub(crate) fn head(self, head: Vec<Box<dyn Render>>) -> Self {
|
|
Self {
|
|
head: Some(head),
|
|
..self
|
|
}
|
|
}
|
|
pub(crate) fn body(self, body: Vec<Box<dyn Render>>) -> 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 }
|
|
}
|
|
}
|