use eframe::egui;
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PreviewMode {
Markdown,
Html,
Latex,
Mermaid,
None,
}
pub fn detect_preview_mode(file_path: Option<&PathBuf>) -> PreviewMode {
if let Some(path) = file_path {
if let Some(ext) = path.extension() {
return match ext.to_str() {
Some("md") | Some("markdown") => PreviewMode::Markdown,
Some("html") | Some("htm") => PreviewMode::Html,
Some("tex") | Some("latex") => PreviewMode::Latex,
Some("mmd") | Some("mermaid") => PreviewMode::Mermaid,
_ => PreviewMode::None,
};
}
}
PreviewMode::None
}
pub fn render_html_preview(ui: &mut egui::Ui, text: &str) {
ui.heading("HTML Preview");
ui.separator();
use scraper::{Html, Selector};
let document = Html::parse_document(text);
if let Ok(selector) = Selector::parse("title") {
for element in document.select(&selector) {
ui.heading(element.text().collect::<String>());
ui.separator();
}
}
if let Ok(selector) = Selector::parse("body") {
for element in document.select(&selector) {
let text = element.text().collect::<Vec<_>>().join(" ");
ui.label(text);
}
} else {
ui.label(text);
}
}
pub fn render_latex_preview(ui: &mut egui::Ui, text: &str) {
ui.heading("LaTeX Preview");
ui.separator();
let mut preview_text = text.to_string();
let substitutions = vec![
(r"\alpha", "α"),
(r"\beta", "β"),
(r"\gamma", "γ"),
(r"\delta", "δ"),
(r"\epsilon", "ε"),
(r"\theta", "θ"),
(r"\lambda", "λ"),
(r"\mu", "μ"),
(r"\pi", "π"),
(r"\sigma", "σ"),
(r"\phi", "φ"),
(r"\omega", "ω"),
(r"\sqrt", "√"),
(r"\int", "∫"),
(r"\sum", "∑"),
(r"\prod", "∏"),
(r"\partial", "∂"),
(r"\nabla", "∇"),
(r"\infty", "∞"),
(r"\pm", "±"),
(r"\times", "×"),
(r"\div", "÷"),
(r"\leq", "≤"),
(r"\geq", "≥"),
(r"\neq", "≠"),
(r"\approx", "≈"),
];
for (latex, unicode) in substitutions {
preview_text = preview_text.replace(latex, unicode);
}
ui.label(&preview_text);
}
pub fn render_mermaid_preview(ui: &mut egui::Ui, text: &str) {
ui.heading("Mermaid Diagram");
ui.separator();
ui.label("Diagram Preview:");
ui.separator();
let lines: Vec<&str> = text.lines().collect();
for line in lines {
let trimmed = line.trim();
if trimmed.is_empty()
|| trimmed.starts_with("graph")
|| trimmed.starts_with("flowchart")
{
continue;
}
if trimmed.contains("-->") || trimmed.contains("->") {
let parts: Vec<&str> = trimmed.split("-->").collect();
if parts.len() == 2 {
ui.horizontal(|ui| {
ui.monospace(format!("[{}]", parts[0].trim()));
ui.label("→");
ui.monospace(format!("[{}]", parts[1].trim()));
});
}
} else {
ui.monospace(trimmed);
}
}
}