use crate::attributes::Attributes;
use crate::Html;
use std::fmt::Display;
fn parse_table_row<T>(row: T, cell_tag: &str) -> String
where
T: IntoIterator,
T::Item: Display,
{
row.into_iter()
.map(|element| {
format!(
"<{tag}>{content}</{tag}>",
tag = cell_tag,
content = element
)
})
.chain(std::iter::once("</tr>".into()))
.fold(String::from("<tr>"), |a, n| a + &n)
}
#[derive(Debug)]
pub struct Table {
thead: Vec<String>,
tbody: Vec<String>,
attr: Attributes,
}
impl Html for Table {
fn to_html_string(&self) -> String {
format!(
"<table{attr}><thead>{thead}</thead><tbody>{tbody}</tbody></table>",
attr = self.attr,
thead = self.thead.join(""),
tbody = self.tbody.join(""),
)
}
}
impl Default for Table {
fn default() -> Self {
Self::new()
}
}
impl<T> From<T> for Table
where
T: IntoIterator,
T::Item: IntoIterator,
<<T as std::iter::IntoIterator>::Item as IntoIterator>::Item: Display,
{
fn from(source: T) -> Self {
let body_rows = source
.into_iter()
.map(|row| parse_table_row(row, "td"))
.collect();
Table {
thead: Vec::new(),
tbody: body_rows,
attr: Attributes::default(),
}
}
}
impl Table {
pub fn new() -> Self {
Table {
thead: Vec::new(),
tbody: Vec::new(),
attr: Attributes::default(),
}
}
pub fn add_attributes<A, S>(&mut self, attributes: A)
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.attr = Attributes::from(attributes);
}
pub fn with_attributes<A, S>(mut self, attributes: A) -> Self
where
A: IntoIterator<Item = (S, S)>,
S: ToString,
{
self.attr = Attributes::from(attributes);
self
}
pub fn add_header_row<T>(&mut self, row: T)
where
T: IntoIterator,
T::Item: Display,
{
self.thead.push(parse_table_row(row, "th"));
}
pub fn with_header_row<T>(mut self, row: T) -> Self
where
T: IntoIterator,
T::Item: Display,
{
self.thead.push(parse_table_row(row, "th"));
self
}
pub fn add_body_row<T>(&mut self, row: T)
where
T: IntoIterator,
T::Item: Display,
{
self.tbody.push(parse_table_row(row, "td"));
}
pub fn with_body_row<T>(mut self, row: T) -> Self
where
T: IntoIterator,
T::Item: Display,
{
self.tbody.push(parse_table_row(row, "td"));
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_arr() {
let arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
let result = Table::from(arr).to_html_string();
assert_eq!(
result,
concat!(
"<table><thead></thead><tbody>",
"<tr><td>1</td><td>2</td><td>3</td></tr>",
"<tr><td>4</td><td>5</td><td>6</td></tr>",
"<tr><td>7</td><td>8</td><td>9</td></tr>",
"</tbody></table>"
)
)
}
#[test]
fn test_from_vec() {
let arr = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
let result = Table::from(&arr).to_html_string();
assert_eq!(
result,
concat!(
"<table><thead></thead><tbody>",
"<tr><td>1</td><td>2</td><td>3</td></tr>",
"<tr><td>4</td><td>5</td><td>6</td></tr>",
"<tr><td>7</td><td>8</td><td>9</td></tr>",
"</tbody></table>"
)
)
}
}