use comrak::{parse_document, format_html_with_plugins, Arena, Options, Plugins};
use comrak::nodes::AstNode;
use mdpdf_theme::{Layout, Theme};
use crate::directives;
use crate::frontmatter::parse_frontmatter;
use crate::highlight::SyntectHighlighter;
pub struct RenderResult {
pub html: String,
pub layout: Layout,
}
pub fn render_to_html(src: &str, theme: Theme, dense: bool) -> RenderResult {
let (fm, body) = parse_frontmatter(src);
let layout = if dense || fm.is_dense() {
Layout::Dense
} else {
Layout::Normal
};
let highlighter = SyntectHighlighter::new(theme.syntect_theme());
let mut options = Options::default();
options.extension.table = true;
options.extension.strikethrough = true;
options.extension.autolink = true;
options.render.unsafe_ = true;
let mut plugins = Plugins::default();
plugins.render.codefence_syntax_highlighter = Some(&highlighter);
let arena = Arena::new();
let root = parse_document(&arena, body, &options);
directives::transform(root);
let rendered = render_ast(root, &options, &plugins);
let css = mdpdf_theme::generate_css(&theme, &layout);
let h1_font_size = match layout {
Layout::Dense => "18pt",
Layout::Normal => "22pt",
};
let header_html = match &fm.title {
Some(title) => {
let subtitle = fm.subtitle.as_deref().map(|s| {
format!("<div class=\"subtitle\">{s}</div>")
}).unwrap_or_default();
let date = fm.date.as_deref().map(|d| {
format!("<div class=\"date\">{d}</div>")
}).unwrap_or_default();
format!(
r#"<div class="doc-header">
<h1 style="border:none;margin:0;padding:0;font-size:{h1_font_size};color:var(--header-fg)">{title}</h1>
{subtitle}
{date}
</div>"#,
)
}
None => String::new(),
};
let html = format!(
r#"<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>{css}</style>
</head>
<body>
{header_html}
{rendered}
</body>
</html>"#,
);
RenderResult { html, layout }
}
fn render_ast<'a>(root: &'a AstNode<'a>, options: &Options, plugins: &Plugins<'_>) -> String {
let mut output = Vec::new();
format_html_with_plugins(root, options, &mut output, plugins)
.expect("HTML rendering failed");
String::from_utf8(output).expect("HTML output was not valid UTF-8")
}