#![allow(clippy::format_push_string)]
#![allow(clippy::uninlined_format_args)]
use crate::config::TableConfig;
pub fn format_tables(content: &str, config: &TableConfig) -> String {
if !config.align {
return content.to_string();
}
let mut result = String::new();
let mut in_table = false;
let mut table_lines = Vec::new();
for line in content.lines() {
let trimmed = line.trim();
if trimmed.starts_with('|') || trimmed.contains('|') {
if !in_table {
in_table = true;
table_lines.clear();
}
table_lines.push(line.to_string());
} else if in_table {
if !table_lines.is_empty() {
result.push_str(&format_table(&table_lines, config));
}
table_lines.clear();
in_table = false;
result.push_str(line);
result.push('\n');
} else {
result.push_str(line);
result.push('\n');
}
}
if !table_lines.is_empty() {
result.push_str(&format_table(&table_lines, config));
}
result
}
fn format_table(lines: &[String], config: &TableConfig) -> String {
if lines.len() < 2 {
return lines.join("\n") + "\n";
}
let rows: Vec<Vec<String>> = lines
.iter()
.map(|line| {
line.split('|')
.map(|cell| cell.trim().to_string())
.filter(|cell| !cell.is_empty())
.collect()
})
.collect();
if rows.is_empty() {
return lines.join("\n") + "\n";
}
let num_cols = rows.iter().map(Vec::len).max().unwrap_or(0);
let mut col_widths = vec![config.min_column_width; num_cols];
for row in &rows {
for (i, cell) in row.iter().enumerate() {
if !cell.chars().all(|c| c == '-' || c == ':') {
col_widths[i] = col_widths[i].max(cell.len());
}
}
}
let mut formatted = String::new();
for row in &rows {
formatted.push('|');
for (col_idx, cell) in row.iter().enumerate() {
let width = col_widths[col_idx];
let padding = " ".repeat(config.padding);
if cell.chars().all(|c| c == '-' || c == ':') {
let sep = if cell.starts_with(':') && cell.ends_with(':') {
format!(":{:-<width$}:", "", width = width - 2)
} else if cell.ends_with(':') {
format!("{:-<width$}:", "", width = width - 1)
} else if cell.starts_with(':') {
format!(":{:-<width$}", "", width = width - 1)
} else {
"-".repeat(width)
};
formatted.push_str(&format!("{padding}{sep}{padding}|"));
} else {
formatted.push_str(&format!(
"{padding}{:<width$}{padding}|",
cell,
width = width
));
}
}
formatted.push('\n');
}
formatted
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_simple_table() {
let input = "|Name|Age|\n|---|---|\n|Alice|30|";
let config = TableConfig::default();
let result = format_tables(input, &config);
assert!(result.contains("Name"));
assert!(result.contains("Alice"));
}
#[test]
fn test_format_table_disabled() {
let input = "|Name|Age|\n|---|---|\n|Alice|30|";
let config = TableConfig {
align: false,
..Default::default()
};
let result = format_tables(input, &config);
assert_eq!(result, input);
}
}