use alloc::borrow::Cow;
use alloc::string::String;
use alloc::vec::Vec;
use core::borrow::Borrow;
use crate::table::Table;
use crate::renderer::{pad, wrap, Renderer, NEWLINE, RenderHint};
use crate::style::{HAlign, Style};
#[derive(Default)]
pub struct Markdown();
impl Renderer for Markdown {
type Output = String;
fn render_with_hints(&self, table: &Table, _: &[RenderHint]) -> Self::Output {
assert!(!table.is_empty(), "table cannot be empty");
let col_widths = table.col_widths(self);
let mut buf = String::new();
print_row(self, table, &col_widths, 0, &mut buf);
print_header_format(table, &col_widths, &mut buf);
for row in 1..table.num_rows() {
print_row(self, table, &col_widths, row, &mut buf);
}
buf
}
}
fn print_header_format(table: &Table, col_widths: &[usize], buf: &mut String) {
buf.push('|');
for (col, &width) in col_widths.iter().enumerate() {
let col = table.col(col);
let styles = col.blended_styles();
let alignment = HAlign::resolve_or_default(&styles);
let alignment = alignment.borrow();
match alignment {
HAlign::Left | HAlign::Right => {
let width = usize::max(2, width);
buf.push_str(&pad(":", '-', width, alignment));
}
HAlign::Centred => {
let width = usize::max(3, width);
buf.push(':');
(2..width).for_each(|_| buf.push('-'));
buf.push(':');
}
}
buf.push('|');
}
buf.push_str(NEWLINE);
}
fn print_row(renderer: &Markdown, table: &Table, col_widths: &[usize], row: usize, buf: &mut String) {
let cell_lines = (0..col_widths.len())
.into_iter()
.map(|col| {
let cell = table.cell(col, row);
let data = cell.as_ref().map_or(Cow::Borrowed(""), |cell| cell.data().render(renderer));
wrap(&data, col_widths[col])
})
.collect::<Vec<_>>();
let cell_styles = (0..col_widths.len())
.into_iter()
.map(|col| {
let cell = table.cell(col, row);
cell.blended_styles()
})
.collect::<Vec<_>>();
let max_lines = cell_lines.iter().map(Vec::len).max().unwrap();
for line in 0..max_lines {
buf.push('|');
for col in 0..col_widths.len() {
let line = cell_lines[col].get(line).map_or("", |line| &line[..]);
let styles = &cell_styles[col];
let alignment = HAlign::resolve_or_default(styles);
let line = pad(line, ' ', col_widths[col], &alignment);
buf.push_str(&line);
buf.push('|');
}
buf.push_str(NEWLINE);
}
}