Skip to main content

merman_render/
math.rs

1//! Optional math rendering hooks.
2//!
3//! Upstream Mermaid renders `$$...$$` fragments via KaTeX and measures the resulting HTML in a
4//! browser DOM. merman is headless and pure-Rust by default, so math rendering is modeled as an
5//! optional, pluggable backend.
6//!
7//! This module only defines an interface; the default implementation is a no-op.
8
9use crate::text::{TextMetrics, TextStyle, WrapMode};
10use merman_core::MermaidConfig;
11
12/// Optional math renderer used to transform label HTML and (optionally) provide measurements.
13///
14/// Implementations should be:
15/// - deterministic (stable output across runs),
16/// - side-effect free (no global mutations),
17/// - non-panicking (return `None` to decline handling).
18pub trait MathRenderer: std::fmt::Debug {
19    /// Attempts to render math fragments within an HTML label string.
20    ///
21    /// If the renderer declines to handle the input, it should return `None`.
22    ///
23    /// The returned string is treated as raw HTML and will still be sanitized by merman before
24    /// emitting into an SVG `<foreignObject>`.
25    fn render_html_label(&self, text: &str, config: &MermaidConfig) -> Option<String>;
26
27    /// Optionally measures the rendered HTML label in pixels.
28    ///
29    /// This is intended to mirror upstream Mermaid's DOM measurement behavior for math labels.
30    /// The default implementation returns `None`.
31    fn measure_html_label(
32        &self,
33        _text: &str,
34        _config: &MermaidConfig,
35        _style: &TextStyle,
36        _max_width_px: Option<f64>,
37        _wrap_mode: WrapMode,
38    ) -> Option<TextMetrics> {
39        None
40    }
41}
42
43/// Default math renderer: does nothing.
44#[derive(Debug, Default, Clone, Copy)]
45pub struct NoopMathRenderer;
46
47impl MathRenderer for NoopMathRenderer {
48    fn render_html_label(&self, _text: &str, _config: &MermaidConfig) -> Option<String> {
49        None
50    }
51}