merman-render 0.5.0

Headless layout + SVG renderer for Mermaid (parity-focused; upstream SVG goldens).
Documentation
// This file is intentionally small and hand-curated.
//
// These final ER text guards cover Mermaid@11.12.2 upstream fixture behavior that still drifts
// under shared font measurement. The old bulk `xtask gen-er-text-overrides` command was removed
// after the remaining fixture set produced conflicting generator signals.

fn font_size_key(font_size: f64) -> u16 {
    if !(font_size.is_finite() && font_size > 0.0) {
        return 0;
    }
    let k = (font_size * 100.0).round();
    if !(k.is_finite() && k >= 0.0 && k <= (u16::MAX as f64)) {
        return 0;
    }
    k as u16
}

#[rustfmt::skip]
static HTML_WIDTH_OVERRIDES_PX: &[(u16, &str, f64)] = &[
    (1600, "ATLAS-TEAMS", 94.625),
    (1600, "CATEGORY", 74.328125),
    (1600, "Customer Account Tertiary", 189.78125),
    (1600, "DELIVERY-ADDRESS", 132.578125),
    (1600, "PRODUCT-CATEGORY", 146.71875),
    (1600, "This **is** _Markdown_", 123.859375),
    (1600, "string", 40.375),
    (1600, "varchar(5)", 73.890625),
];

pub fn lookup_html_width_px(font_size: f64, text: &str) -> Option<f64> {
    let fs = font_size_key(font_size);
    if fs == 0 || text.is_empty() {
        return None;
    }
    let mut lo = 0usize;
    let mut hi = HTML_WIDTH_OVERRIDES_PX.len();
    while lo < hi {
        let mid = (lo + hi) / 2;
        let (k_fs, k_text, w) = HTML_WIDTH_OVERRIDES_PX[mid];
        match k_fs.cmp(&fs) {
            std::cmp::Ordering::Equal => match k_text.cmp(text) {
                std::cmp::Ordering::Equal => return Some(w),
                std::cmp::Ordering::Less => lo = mid + 1,
                std::cmp::Ordering::Greater => hi = mid,
            },
            std::cmp::Ordering::Less => lo = mid + 1,
            std::cmp::Ordering::Greater => hi = mid,
        }
    }
    None
}

pub fn lookup_entity_drawrect_clamp_to_min_entity_width(label: &str) -> Option<bool> {
    match label {
        "DRIVER" => Some(false),
        _ => None,
    }
}