use std::rc::Rc;
use crate::{
AttributeName, Block, ColumnStyle, DocumentAttribute, DocumentAttributeAssignment, Error,
InlineNode, Paragraph, TableColumn, Verbatim, blocks::table::CellSpecifier,
};
use super::{
ParserState, document_parser, inline_processing::adjust_and_log_parse_error,
state::BlockContext,
};
pub(crate) fn parse_table_cell<'a>(
content: &'a str,
state: &mut ParserState<'a>,
cell_start_offset: usize,
spec: &CellSpecifier,
) -> Result<TableColumn<'a>, Error> {
if spec.style == Some(ColumnStyle::Literal) {
let location = if content.is_empty() {
state.create_location(cell_start_offset, cell_start_offset)
} else {
state.create_block_location(0, content.len(), cell_start_offset)
};
let blocks = vec![Block::Paragraph(Paragraph::new(
vec![InlineNode::VerbatimText(Verbatim {
content,
location: location.clone(),
})],
location,
))];
return Ok(TableColumn::with_format(
blocks,
spec.colspan,
spec.rowspan,
spec.halign,
spec.valign,
spec.style,
));
}
let mut initial_attributes = Vec::new();
let blocks = if spec.style == Some(ColumnStyle::AsciiDoc) {
let outer_attributes = Rc::clone(&state.document_attributes);
let outer_parent_attributes = state
.nested_parent_attributes
.replace(Rc::clone(&state.document_attributes));
let outer_hardbreaks = state.hardbreaks;
let outer_context = std::mem::replace(&mut state.block_context, BlockContext::Document);
let outer_toc_len = state.toc_entries.len();
let outer_pending_callouts = std::mem::take(&mut state.pending_callouts);
initial_attributes = crate::document_attribute::initialize_nested_attributes(Rc::make_mut(
&mut state.document_attributes,
));
let result = document_parser::nested_document_blocks(
content,
state,
cell_start_offset,
&mut initial_attributes,
);
state.document_attributes = outer_attributes;
state.nested_parent_attributes = outer_parent_attributes;
state.hardbreaks = outer_hardbreaks;
state.block_context = outer_context;
state.toc_entries.truncate(outer_toc_len);
state.pending_callouts = outer_pending_callouts;
result
} else {
document_parser::blocks_for_table_cell(content, state, cell_start_offset)
}
.unwrap_or_else(|error| {
adjust_and_log_parse_error(
&error,
content,
cell_start_offset,
state,
"Failed parsing table cell content as blocks",
);
Ok(Vec::new())
})?;
let mut column = TableColumn::with_format(
blocks,
spec.colspan,
spec.rowspan,
spec.halign,
spec.valign,
spec.style,
);
column.initial_attributes = initial_attributes;
Ok(column)
}
pub(crate) fn normalize_nested_header<'a>(
state: &mut ParserState<'a>,
header: Vec<Result<Block<'a>, Error>>,
initial_attributes: &mut Vec<(AttributeName<'a>, DocumentAttributeAssignment<'a>)>,
) -> Result<Vec<Block<'a>>, Error> {
let mut header = header.into_iter().collect::<Result<Vec<_>, _>>()?;
let normalized = crate::document_attribute::normalize_toc_attributes(Rc::make_mut(
&mut state.document_attributes,
));
for block in &mut header {
if let Block::DocumentAttribute(event) = block
&& event.is_accepted()
&& let Some((_, assignment)) = normalized.iter().find(|(name, _)| *name == event.name)
{
*event = DocumentAttribute::accepted(
event.name.clone(),
assignment.clone(),
event.location.clone(),
);
}
}
initial_attributes.extend(normalized);
Ok(header)
}