late2htm 0.1.0

A Rust library for converting LaTeX-formatted text into HTML with minimal styling.
Documentation
use crate::ast::LatexNode;

pub fn generate_html(node: &LatexNode) -> String {
    match node {
        LatexNode::Document { preamble: _, body } => {
            let content = body.iter().map(generate_html).collect::<Vec<_>>().join("\n");
            format!("<html><body>{}</body></html>", content)
        }
        LatexNode::Section(title) => format!("<h1>{}</h1>", title),
        LatexNode::Subsection(title) => format!("<h2>{}</h2>", title),
        LatexNode::Subsubsection(title) => format!("<h3>{}</h3>", title),
        LatexNode::Paragraph(title) => format!("<h4>{}</h4>" , title),
        LatexNode::Subparagraph(title) => format!("<h5>{}</h5>", title),

        LatexNode::Text(text) => text.clone(),
        LatexNode::Bold(text) => format!("<b>{}</b>", text),
        LatexNode::Italic(text) => format!("<i>{}</i>", text),
        LatexNode::Underline(text) => format!("<u>{}</u>", text),
        LatexNode::Emphasized(text) => format!("<em>{}</em>", text),
        LatexNode::Colored { color, content } => format!("<span style=\"color:{}\">{}</span>", color, content),
        LatexNode::FontSize { size, content } => format!("<span style=\"font-size:{}\">{}</span>", size, content),

        LatexNode::InlineMath(expr) => format!("<span class=\"math-inline\">{}</span>", expr),
        LatexNode::DisplayMath(expr) => format!("<div class=\"math-display\">{}</div>", expr),
        LatexNode::MathEnvironment { name, content } => format!("<div class=\"math-env\" data-env=\"{}\">{}</div>", name, content),

        LatexNode::Itemize(items) => {
            let content = items.iter().map(generate_html).collect::<Vec<_>>().join("");
            format!("<ul>{}</ul>", content)
        }
        LatexNode::Enumerate(items) => {
            let content = items.iter().map(generate_html).collect::<Vec<_>>().join("");
            format!("<ol>{}</ol>", content)
        }
        LatexNode::Description(pairs) => {
            let items = pairs.iter().map(|(k, v)| format!("<dt>{}</dt><dd>{}</dd>", k, v)).collect::<Vec<_>>().join("");
            format!("<dl>{}</dl>", items)
        }
        LatexNode::ListItem(item) => format!("<li>{}</li>", item),

        LatexNode::Table { alignment: _, rows, caption } => {
            let body = rows.iter().map(|row| {
                let cols = row.iter().map(|c| format!("<td>{}</td>", c)).collect::<Vec<_>>().join("");
                format!("<tr>{}</tr>", cols)
            }).collect::<Vec<_>>().join("");
            let caption_html = caption.as_ref().map(|c| format!("<caption>{}</caption>", c)).unwrap_or_default();
            format!("<table>{}{}</table>", caption_html, body)
        }

        LatexNode::Image { path, width, height, caption } => {
            let mut attrs = format!("src=\"{}\"", path);
            if let Some(w) = width { attrs += &format!(" width=\"{}\"", w); }
            if let Some(h) = height { attrs += &format!(" height=\"{}\"", h); }
            let img_tag = format!("<img {} />", attrs);
            if let Some(c) = caption {
                format!("<figure>{}<figcaption>{}</figcaption></figure>", img_tag, c)
            } else {
                img_tag
            }
        }
        LatexNode::Figure { content, caption } => {
            let inner = content.iter().map(generate_html).collect::<Vec<_>>().join("");
            let cap = caption.as_ref().map(|c| format!("<figcaption>{}</figcaption>", c)).unwrap_or_default();
            format!("<figure>{}{}</figure>", inner, cap)
        }

        LatexNode::Hyperlink { url, text } => format!("<a href=\"{}\">{}</a>", url, text),
        LatexNode::Footnote(text) => format!("<sup class=\"footnote\">{}</sup>", text),
        LatexNode::Label(label) => format!("<span id=\"{}\"></span>", label),
        LatexNode::Ref(reference) => format!("<a href=\"#{}\">[ref]</a>", reference),
        LatexNode::Cite(key) => format!("<span class=\"citation\">[{}]</span>", key),

        LatexNode::Bibliography { style: _, items } => {
            let list = items.iter().map(generate_html).collect::<Vec<_>>().join("");
            format!("<div class=\"bibliography\">{}</div>", list)
        }
        LatexNode::BibItem { key, content } => {
            let inner = content.iter().map(generate_html).collect::<Vec<_>>().join("");
            format!("<div id=\"bib-{}\">{}</div>", key, inner)
        }

        LatexNode::NewCommand { name, args, definition } => format!("<!-- newcommand: {}({}) = {} -->", name, args, definition),
        LatexNode::RenewCommand { name, args, definition } => format!("<!-- renewcommand: {}({}) = {} -->", name, args, definition),

        LatexNode::Environment { name, content } => {
            let inner = content.iter().map(generate_html).collect::<Vec<_>>().join("");
            format!("<div class=\"env-{}\">{}</div>", name, inner)
        }

        LatexNode::HorizontalRule => "<hr />".to_string(),
        LatexNode::PageBreak => "<div style=\"page-break-after: always;\"></div>".to_string(),
        LatexNode::TableOfContents => "<!-- Table of contents would be generated here -->".to_string(),
        LatexNode::RawLatex(raw) => format!("<!-- Raw LaTeX: {} -->", raw),
    }
}