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}