2023-10-31 20:26:34 -04:00
|
|
|
use super::macros::intermediate;
|
|
|
|
use super::table_row::ITableRow;
|
2023-10-29 17:29:16 -04:00
|
|
|
use crate::error::CustomError;
|
2023-12-22 17:11:52 -05:00
|
|
|
use crate::intermediate::table_group::ITableGroup;
|
2023-12-21 14:56:58 -05:00
|
|
|
use organic::types::StandardProperties;
|
2023-10-27 17:08:58 -04:00
|
|
|
|
2023-10-31 20:26:34 -04:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub(crate) struct ITable {
|
2023-12-22 17:11:52 -05:00
|
|
|
pub(crate) children: Vec<ITableGroup>,
|
2023-12-21 14:56:58 -05:00
|
|
|
pub(crate) post_blank: organic::types::PostBlank,
|
2023-10-31 20:26:34 -04:00
|
|
|
}
|
|
|
|
|
2023-12-19 17:09:11 -05:00
|
|
|
intermediate!(
|
|
|
|
ITable,
|
|
|
|
&'orig organic::types::Table<'parse>,
|
|
|
|
original,
|
2023-12-21 13:53:56 -05:00
|
|
|
intermediate_context,
|
2023-12-19 17:09:11 -05:00
|
|
|
{
|
2023-12-22 00:08:06 -05:00
|
|
|
// Separate groups by lines, multiple contiguous lines are the same as one.
|
|
|
|
// If there is only one group, it is a tbody.
|
|
|
|
// If there are more than one group, the first is thead and the rest are tbody.
|
|
|
|
|
|
|
|
let sections = group_into_sections(&original.children);
|
|
|
|
|
2023-12-22 17:11:52 -05:00
|
|
|
let children = if sections.len() == 1 {
|
|
|
|
// If there is only one section, then it is a body.
|
2023-12-19 17:09:11 -05:00
|
|
|
let mut ret = Vec::new();
|
2023-12-22 17:11:52 -05:00
|
|
|
for group in sections.into_iter() {
|
|
|
|
let mut rows = Vec::new();
|
|
|
|
for obj in group.into_iter() {
|
|
|
|
rows.push(ITableRow::new(intermediate_context.clone(), obj).await?)
|
|
|
|
}
|
|
|
|
ret.push(ITableGroup::Body(rows));
|
|
|
|
}
|
|
|
|
ret
|
|
|
|
} else {
|
|
|
|
// If there are more than one section, the first is a head and the rest are body.
|
|
|
|
let mut ret = Vec::new();
|
|
|
|
let mut sections = sections.into_iter();
|
|
|
|
if let Some(group) = sections.next() {
|
|
|
|
let mut rows = Vec::new();
|
|
|
|
for obj in group.into_iter() {
|
|
|
|
rows.push(ITableRow::new(intermediate_context.clone(), obj).await?)
|
|
|
|
}
|
|
|
|
ret.push(ITableGroup::Head(rows));
|
|
|
|
}
|
|
|
|
for group in sections {
|
|
|
|
let mut rows = Vec::new();
|
|
|
|
for obj in group.into_iter() {
|
|
|
|
rows.push(ITableRow::new(intermediate_context.clone(), obj).await?)
|
|
|
|
}
|
|
|
|
ret.push(ITableGroup::Body(rows));
|
2023-12-19 17:09:11 -05:00
|
|
|
}
|
|
|
|
ret
|
|
|
|
};
|
2023-10-31 20:26:34 -04:00
|
|
|
|
2023-12-21 14:56:58 -05:00
|
|
|
Ok(ITable {
|
|
|
|
children,
|
|
|
|
post_blank: original.get_post_blank(),
|
|
|
|
})
|
2023-12-19 17:09:11 -05:00
|
|
|
}
|
|
|
|
);
|
2023-12-22 00:08:06 -05:00
|
|
|
|
|
|
|
enum GroupIntoSectionsState<'orig, 'parse> {
|
|
|
|
NonSection,
|
|
|
|
Section(Vec<&'orig organic::types::TableRow<'parse>>),
|
|
|
|
}
|
|
|
|
|
|
|
|
fn group_into_sections<'orig, 'parse>(
|
|
|
|
rows: &'orig Vec<organic::types::TableRow<'parse>>,
|
|
|
|
) -> Vec<Vec<&'orig organic::types::TableRow<'parse>>> {
|
|
|
|
let mut sections = Vec::new();
|
|
|
|
let mut rows = rows.into_iter();
|
|
|
|
let mut state = GroupIntoSectionsState::NonSection;
|
|
|
|
loop {
|
|
|
|
state = match (state, rows.next()) {
|
|
|
|
(GroupIntoSectionsState::NonSection, None) => break,
|
|
|
|
(GroupIntoSectionsState::NonSection, Some(row)) if row.children.is_empty() => {
|
|
|
|
GroupIntoSectionsState::NonSection
|
|
|
|
}
|
|
|
|
(GroupIntoSectionsState::NonSection, Some(row)) => {
|
|
|
|
GroupIntoSectionsState::Section(vec![row])
|
|
|
|
}
|
|
|
|
(GroupIntoSectionsState::Section(section), None) => {
|
|
|
|
sections.push(section);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
(GroupIntoSectionsState::Section(section), Some(row)) if row.children.is_empty() => {
|
|
|
|
sections.push(section);
|
|
|
|
GroupIntoSectionsState::NonSection
|
|
|
|
}
|
|
|
|
(GroupIntoSectionsState::Section(mut section), Some(row)) => {
|
|
|
|
section.push(row);
|
|
|
|
GroupIntoSectionsState::Section(section)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sections
|
|
|
|
}
|