parity(7): table cell alignment markers (|:--|--:|:--:|)
The Markdown-style alignment anchors on a table's header-separator row now propagate from the lexer through the parser into the AST, and the HTML renderer emits a `style="text-align: …;"` attribute on each affected `<th>` / `<td>`. |:--| → left |--:| → right |:--:| → center |---| → default (no style attr) Encoding choice: rather than threading the source string into the parser, the lexer now extracts per-cell alignment when it recognises the separator row and carries the `Vec<TableAlign>` inline on the `TableHeaderRow` token. The parser unpacks it into `TableNode`'s new `alignments: Vec<TableAlign>` field. Cells past the end of the vector render with the default alignment. `TableAlign` lives in `nuwiki_core::ast::block` alongside the table nodes and is re-exported via `nuwiki_core::ast`. Tests: 4 new in crates/nuwiki-core/tests/vimwiki_table_alignment.rs covering plain dashes, all three anchor flavours, the HTML output shape, and the no-style-attr case. The existing `vimwiki_lexer::table_header_separator_row` was updated to assert the new payload shape. Gates: 425 Rust / 39 Neovim / 12 Vim. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -310,7 +310,7 @@ impl HtmlRenderer {
|
||||
in_tbody = true;
|
||||
}
|
||||
}
|
||||
self.render_table_row(row, row_idx, &layout, w)?;
|
||||
self.render_table_row(row, row_idx, &layout, &n.alignments, w)?;
|
||||
}
|
||||
if in_thead {
|
||||
w.write_all(b"</thead>\n")?;
|
||||
@@ -326,6 +326,7 @@ impl HtmlRenderer {
|
||||
n: &TableRowNode,
|
||||
row_idx: usize,
|
||||
layout: &[Vec<CellLayout>],
|
||||
alignments: &[crate::ast::TableAlign],
|
||||
w: &mut dyn Write,
|
||||
) -> io::Result<()> {
|
||||
w.write_all(b"<tr>")?;
|
||||
@@ -341,7 +342,11 @@ impl HtmlRenderer {
|
||||
match info {
|
||||
CellLayout::Skip => continue,
|
||||
CellLayout::Lead { colspan, rowspan } => {
|
||||
self.render_table_cell(cell, n.is_header, colspan, rowspan, w)?;
|
||||
let align = alignments
|
||||
.get(col_idx)
|
||||
.copied()
|
||||
.unwrap_or(crate::ast::TableAlign::Default);
|
||||
self.render_table_cell(cell, n.is_header, colspan, rowspan, align, w)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -354,6 +359,7 @@ impl HtmlRenderer {
|
||||
is_header: bool,
|
||||
colspan: u32,
|
||||
rowspan: u32,
|
||||
align: crate::ast::TableAlign,
|
||||
w: &mut dyn Write,
|
||||
) -> io::Result<()> {
|
||||
let tag = if is_header { "th" } else { "td" };
|
||||
@@ -364,6 +370,15 @@ impl HtmlRenderer {
|
||||
if rowspan > 1 {
|
||||
write!(w, " rowspan=\"{rowspan}\"")?;
|
||||
}
|
||||
let align_attr = match align {
|
||||
crate::ast::TableAlign::Left => Some("left"),
|
||||
crate::ast::TableAlign::Right => Some("right"),
|
||||
crate::ast::TableAlign::Center => Some("center"),
|
||||
crate::ast::TableAlign::Default => None,
|
||||
};
|
||||
if let Some(a) = align_attr {
|
||||
write!(w, " style=\"text-align: {a};\"")?;
|
||||
}
|
||||
write!(w, ">")?;
|
||||
self.render_inlines(&n.children, w)?;
|
||||
write!(w, "</{tag}>")
|
||||
|
||||
Reference in New Issue
Block a user