heartwood every commit a ring

Render GFM tables in markdown via comrak table extension

42e3f2dd by Isaac Bythewood · 6 days ago

Render GFM tables in markdown via comrak table extension

Enables opts.extension.table and adds a NodeValue::Table handler that
emits thead/tbody with bootstrap .table classes, preserves per-column
alignment from the |---:| syntax, and wraps the table in
.table-responsive for mobile overflow. Without the handler, comrak's
table nodes fell through to the default child-iteration fallback and
the structure was lost.
modified src/markdown.rs
@@ -1,5 +1,5 @@use comrak::{    nodes::{AstNode, NodeValue},    nodes::{AstNode, NodeValue, TableAlignment},    Arena, ComrakOptions,};use std::cell::RefCell;
@@ -8,6 +8,7 @@ use std::fmt::Write;fn options() -> ComrakOptions {    let mut opts = ComrakOptions::default();    opts.extension.strikethrough = true;    opts.extension.table = true;    opts.render.unsafe_ = true;    opts}
@@ -124,6 +125,39 @@ fn render_node<'a>(node: &'a AstNode<'a>, out: &mut String, opts: &ComrakOptions        NodeValue::HtmlBlock(h) => {            out.push_str(&h.literal);        }        NodeValue::Table(t) => {            let alignments = &t.alignments;            out.push_str(                "<div class=\"block-rich-text\"><div class=\"table-responsive\"><table class=\"table\">",            );            let mut rows = node.children();            if let Some(header) = rows.next() {                out.push_str("<thead><tr>");                for (i, cell) in header.children().enumerate() {                    let style = align_style(alignments.get(i).copied());                    write!(out, "<th{style}>").ok();                    for child in cell.children() {                        render_inline(child, out, opts);                    }                    out.push_str("</th>");                }                out.push_str("</tr></thead>");            }            out.push_str("<tbody>");            for row in rows {                out.push_str("<tr>");                for (i, cell) in row.children().enumerate() {                    let style = align_style(alignments.get(i).copied());                    write!(out, "<td{style}>").ok();                    for child in cell.children() {                        render_inline(child, out, opts);                    }                    out.push_str("</td>");                }                out.push_str("</tr>");            }            out.push_str("</tbody></table></div></div>\n");        }        _ => {            // Fallback: emit raw HTML for unhandled block types via comrak            let buf = RefCell::new(String::new());
@@ -136,6 +170,15 @@ fn render_node<'a>(node: &'a AstNode<'a>, out: &mut String, opts: &ComrakOptions    }}fn align_style(a: Option<TableAlignment>) -> &'static str {    match a {        Some(TableAlignment::Left) => " style=\"text-align:left\"",        Some(TableAlignment::Right) => " style=\"text-align:right\"",        Some(TableAlignment::Center) => " style=\"text-align:center\"",        _ => "",    }}fn is_paragraph_only_image<'a>(para: &'a AstNode<'a>) -> bool {    let mut iter = para.children();    let first = iter.next();