///|
pub struct ReportTable {
columns : Array[String]
rows : Array[Array[String]]
} derive(Debug, Eq)
///|
pub fn table(
columns : Array[String],
rows : Array[Array[String]],
) -> ReportTable {
{ columns, rows }
}
///|
pub fn ReportTable::validate(self : ReportTable) -> Array[String] {
let errors : Array[String] = []
if self.columns.length() == 0 {
errors.push("table needs at least one column")
}
for _, row in self.rows {
if row.length() != self.columns.length() {
errors.push(
"row has {row.length()} cells, expected {self.columns.length()}",
)
}
}
errors
}
///|
fn escape_table(text : String) -> String {
escape_html(text).replace(old="|", new="\\|")
}
///|
pub fn ReportTable::to_markdown(self : ReportTable) -> String {
let lines : Array[String] = []
lines.push("| " + self.columns.map(escape_table).join(" | ") + " |")
lines.push("| " + self.columns.map(fn(_) { "---" }).join(" | ") + " |")
for row in self.rows {
lines.push("| " + row.map(escape_table).join(" | ") + " |")
}
lines.join("\n")
}
///|
fn csv_cell(text : String) -> String {
"\"" + text.replace(old="\"", new="\"\"") + "\""
}
///|
pub fn ReportTable::to_csv(self : ReportTable) -> String {
let lines : Array[String] = [self.columns.map(csv_cell).join(",")]
for row in self.rows {
lines.push(row.map(csv_cell).join(","))
}
lines.join("\n")
}
///|
pub fn ReportTable::to_html(self : ReportTable) -> String {
let header = "" +
self.columns.map(fn(item) { "| " + escape_html(item) + " | " }).join("") +
"
"
let body : Array[String] = []
for row in self.rows {
body.push(
"" +
row.map(fn(item) { "| " + escape_html(item) + " | " }).join("") +
"
",
)
}
"" +
header +
"" +
body.join("") +
"
"
}
///|
pub fn ReportTable::row_count(self : ReportTable) -> Int {
self.rows.length()
}
///|
pub fn ReportTable::column_count(self : ReportTable) -> Int {
self.columns.length()
}
///|
pub fn ReportTable::is_rectangular(self : ReportTable) -> Bool {
self.validate().length() == 0
}