use super::hooks::ParseHooks;
use super::inline;
use crate::ast::options::AstOptions;
use crate::ast::tokens::span::Span;
use crate::ast::tokens::token::{Block, Table, TableCell, TableCellAlignment, TableRow};
pub fn is_table_delimiter(line: &str) -> bool {
let stripped = line.trim();
if stripped.is_empty() {
return false;
}
let s = stripped.strip_prefix('|').unwrap_or(stripped);
let s = s.strip_suffix('|').unwrap_or(s);
let cells: Vec<&str> = s.split('|').collect();
if cells.is_empty() {
return false;
}
cells.iter().all(|c| {
let t = c.trim();
!t.is_empty() && t.chars().all(|ch| ch == '-' || ch == ':') && t.contains('-')
})
}
pub fn is_table_start(lines: &[&str], pos: usize) -> bool {
if pos + 1 >= lines.len() {
return false;
}
let header = lines[pos];
let delimiter = lines[pos + 1];
header.contains('|') && is_table_delimiter(delimiter)
}
pub fn parse_delimiter_alignments(line: &str) -> Vec<TableCellAlignment> {
let stripped = line.trim();
let s = stripped.strip_prefix('|').unwrap_or(stripped);
let s = s.strip_suffix('|').unwrap_or(s);
s.split('|')
.map(|cell| {
let t = cell.trim();
let left = t.starts_with(':');
let right = t.ends_with(':');
match (left, right) {
(true, true) => TableCellAlignment::Center,
(true, false) => TableCellAlignment::Left,
(false, true) => TableCellAlignment::Right,
(false, false) => TableCellAlignment::Default,
}
})
.collect()
}
pub fn split_table_row(line: &str) -> Vec<String> {
let stripped = line.trim();
let s = stripped.strip_prefix('|').unwrap_or(stripped);
let s = s.strip_suffix('|').unwrap_or(s);
s.split('|').map(|c| c.trim().to_string()).collect()
}
#[allow(clippy::too_many_arguments)]
pub fn build_table(
header_line: &str,
_delimiter_line: &str,
alignments: Vec<TableCellAlignment>,
body_lines: &[&str],
options: Option<&AstOptions>,
hooks: &ParseHooks,
) -> Block {
let header_cells: Vec<String> = split_table_row(header_line);
let header = TableRow {
cells: header_cells
.iter()
.map(|c| TableCell {
children: inline::parse_inline_with_hooks(c, options, None, hooks),
})
.collect(),
};
let rows: Vec<TableRow> = body_lines
.iter()
.map(|line| {
let cells: Vec<String> = split_table_row(line);
TableRow {
cells: cells
.iter()
.map(|c| TableCell {
children: inline::parse_inline_with_hooks(c, options, None, hooks),
})
.collect(),
}
})
.collect();
Block::Table {
table: Table {
header,
rows,
alignments,
},
attrs: None,
pos: Span::default(),
}
}