use crate::attributes::Attributes;
use crate::Html;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum HeadContent {
Link {
href: String,
rel: String,
attr: Attributes,
},
Meta { attr: Attributes },
ScriptLink { src: String, attr: Attributes },
ScriptLiteral { code: String },
Style { css: String, attr: Attributes },
Title { content: String },
}
impl Html for HeadContent {
fn to_html_string(&self) -> String {
match self {
Self::Link { href, rel, attr } => {
format!(r#"<link href="{}" rel="{}"{}>"#, href, rel, attr)
}
Self::Meta { attr } => format!("<meta{}>", attr),
Self::ScriptLink { src, attr } => format!(r#"<script src="{}"{}></script>"#, src, attr),
Self::ScriptLiteral { code } => format!("<script>{}</script>", code),
Self::Style { css, attr } => format!("<style{}>{}</style>", attr, css),
Self::Title { content } => format!("<title>{}</title>", content),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum BodyContent {
Header {
level: u8,
content: String,
attr: Attributes,
},
Image {
src: String,
alt: String,
attr: Attributes,
},
Link {
href: String,
content: String,
attr: Attributes,
},
Paragraph { content: String, attr: Attributes },
Preformatted { content: String, attr: Attributes },
Raw { content: String },
}
impl Html for BodyContent {
fn to_html_string(&self) -> String {
match self {
BodyContent::Header {
level,
content,
attr,
} => format!(
"<h{level}{attr}>{content}</h{level}>",
level = level,
attr = attr,
content = content
),
BodyContent::Paragraph { content, attr } => {
format!("<p{attr}>{content}</p>", attr = attr, content = content)
}
BodyContent::Preformatted { content, attr } => {
format!("<pre{attr}>{content}</pre>", attr = attr, content = content)
}
BodyContent::Link {
href,
content,
attr,
} => format!(
r#"<a href="{href}"{attr}>{content}</a>"#,
href = href,
attr = attr,
content = content
),
BodyContent::Image { src, alt, attr } => format!(
r#"<img src="{src}" alt="{alt}"{attr}>"#,
src = src,
alt = alt,
attr = attr
),
BodyContent::Raw { content } => content.to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
mod head_content {
use super::*;
use test_case::test_case;
#[test_case(HeadContent::Title {content: "Page Title".into()}, "<title>Page Title</title>"; "test_title")]
fn to_html_string(sut: HeadContent, expected: &str) {
assert_eq!(sut.to_html_string(), expected);
}
}
mod body_content {
use super::*;
#[test]
fn test_header_1() {
let sut = BodyContent::Header {
level: 1,
content: "Main Heading".into(),
attr: Attributes::empty(),
};
assert_eq!(sut.to_html_string(), "<h1>Main Heading</h1>")
}
#[test]
fn test_header_6() {
let sut = BodyContent::Header {
level: 6,
content: "Sub Heading".into(),
attr: vec![("id", "sub"), ("class", "heading")].into(),
};
assert_eq!(
sut.to_html_string(),
r#"<h6 id="sub" class="heading">Sub Heading</h6>"#
)
}
#[test]
fn test_image() {
let sut = BodyContent::Image {
src: "myImage.jpg".into(),
alt: "This is alternate text".into(),
attr: Attributes::from(vec![("class", "images")]),
};
assert_eq!(
sut.to_html_string(),
r#"<img src="myImage.jpg" alt="This is alternate text" class="images">"#
)
}
#[test]
fn test_link() {
let sut = BodyContent::Link {
href: "https://rust-lang.org".into(),
content: "Rust Homepage".into(),
attr: Attributes::empty(),
};
assert_eq!(
sut.to_html_string(),
r#"<a href="https://rust-lang.org">Rust Homepage</a>"#
)
}
#[test]
fn test_paragraph() {
let sut = BodyContent::Paragraph {
content: "This is sample text".into(),
attr: vec![
("class", "text"),
("id", "test-text"),
("onclick", "something()"),
]
.into(),
};
assert_eq!(
sut.to_html_string(),
r#"<p class="text" id="test-text" onclick="something()">This is sample text</p>"#
)
}
#[test]
fn test_preformatted() {
let sut = BodyContent::Preformatted {
content: "Pre => formatted".into(),
attr: Attributes::empty(),
};
assert_eq!(sut.to_html_string(), r#"<pre>Pre => formatted</pre>"#)
}
}
}