mdbook-plotly 0.3.0

A mdbook preprocessor that renders plot code blocks (e.g., ```plot) into interactive or static charts during book build.
Documentation
use super::common::parse_color_bar;
use super::until::{Color, must_translate_from_context};
use crate::code_handler::parse_context::ParseContext;
use crate::{translate_enum_with_config, translate_with_config};
use anyhow::Result;
use plotly::{Contour, Trace};

pub fn parse_contour_data(
    ct_obj: &mut serde_json::Value,
    context: &ParseContext<'_>,
) -> Result<Box<Contour<Vec<f64>, f64, f64>>> {
    let z: Vec<Vec<f64>> = must_translate_from_context(ct_obj, context, "z")?;
    let contour = if ct_obj.get("x").is_some() {
        let x: Vec<f64> = must_translate_from_context(ct_obj, context, "x")?;
        let y: Vec<f64> = must_translate_from_context(ct_obj, context, "y")?;
        Contour::new(x, y, z)
    } else {
        Contour::new_z(z)
    };

    let contour = translate_with_config! {
        contour,
        ct_obj,
        context.map(),
        context.map_eval(),
        (x0, f64),
        (dx, f64),
        (y0, f64),
        (dy, f64),
        (opacity, f64),
        (n_contours, usize),
        (connect_gaps, bool),
        (hover_on_gaps, bool),
        (show_legend, bool),
        (transpose, bool),
        (auto_contour, bool),
        (auto_color_scale, bool),
        (reverse_scale, bool),
        (show_scale, bool),
        (zauto, bool),
        (fill_color, Color),
    }?;

    use plotly::common::HoverInfo;
    let contour = translate_enum_with_config! {
        contour,
        ct_obj,
        context.map(),
        context.map_eval(),
        (hover_info, {
            "all" => HoverInfo::All,
            "x" => HoverInfo::X,
            "y" => HoverInfo::Y,
            "z" => HoverInfo::Z,
            "x+y" => HoverInfo::XAndY,
            "x+z" => HoverInfo::XAndZ,
            "y+z" => HoverInfo::YAndZ,
            "x+y+z" => HoverInfo::XAndYAndZ,
            "text" => HoverInfo::Text,
            "name" => HoverInfo::Name,
            "none" => HoverInfo::None,
            "skip" => HoverInfo::Skip,
        }),
    }?;

    let contour = if let Some(contours_obj) = ct_obj.get_mut("contours")
        && contours_obj.is_object()
    {
        use plotly::traces::contour::Contours;
        let contours = translate_with_config! {
            Contours::new(),
            contours_obj,
            context.map(),
            context.map_eval(),
            (start, f64),
            (end, f64),
            (size, f64),
        }?;

        use plotly::traces::contour::Coloring;
        let contours = translate_enum_with_config! {
            contours,
            contours_obj,
            context.map(),
            context.map_eval(),
            (coloring, {
                "fill"        => Coloring::Fill,
                "heatmap"     => Coloring::HeatMap,
                "lines"       => Coloring::Lines,
                "none"        => Coloring::None,
            }),
        }?;
        contour.contours(contours)
    } else {
        contour
    };

    let contour = if let Some(line_obj) = ct_obj.get_mut("line")
        && line_obj.is_object()
    {
        use plotly::common::Line;
        let line = translate_with_config! {
            Line::new(),
            line_obj,
            context.map(),
            context.map_eval(),
            (color, Color),
            (width, f64),
        }?;
        use plotly::common::DashType;
        let line = translate_enum_with_config! {
            line,
            line_obj,
            context.map(),
            context.map_eval(),
            (dash, {
                "solid" => DashType::Solid,
                "dot" => DashType::Dot,
                "dash" => DashType::Dash,
                "longdash" => DashType::LongDash,
                "dashdot" => DashType::DashDot,
                "longdashdot" => DashType::LongDashDot,
            }),
        }?;
        contour.line(line)
    } else {
        contour
    };

    let contour = if let Some(color_bar_obj) = ct_obj.get_mut("color_bar")
        && color_bar_obj.is_object()
    {
        let color_bar = parse_color_bar(color_bar_obj, context)?;
        contour.color_bar(color_bar)
    } else {
        contour
    };

    let contour = if ct_obj.get("color_scale").is_some() {
        use plotly::common::{ColorScale, ColorScalePalette};
        let color_scale_str: String = must_translate_from_context(ct_obj, context, "color_scale")?;
        let palette = match color_scale_str.to_lowercase().as_str() {
            "greys" => ColorScalePalette::Greys,
            "ylgnbu" => ColorScalePalette::YlGnBu,
            "greens" => ColorScalePalette::Greens,
            "ylorrd" => ColorScalePalette::YlOrRd,
            "bluered" => ColorScalePalette::Bluered,
            "rdbu" => ColorScalePalette::RdBu,
            "reds" => ColorScalePalette::Reds,
            "blues" => ColorScalePalette::Blues,
            "picnic" => ColorScalePalette::Picnic,
            "rainbow" => ColorScalePalette::Rainbow,
            "portland" => ColorScalePalette::Portland,
            "jet" => ColorScalePalette::Jet,
            "hot" => ColorScalePalette::Hot,
            "blackbody" => ColorScalePalette::Blackbody,
            "earth" => ColorScalePalette::Earth,
            "electric" => ColorScalePalette::Electric,
            "viridis" => ColorScalePalette::Viridis,
            "cividis" => ColorScalePalette::Cividis,
            _ => return Err(anyhow::anyhow!("unknown color_scale: {}", color_scale_str)),
        };
        contour.color_scale(ColorScale::Palette(palette))
    } else {
        contour
    };

    Ok(contour)
}

pub fn parse_contour_trace(
    ct_obj: &mut serde_json::Value,
    context: &ParseContext<'_>,
) -> Result<Box<dyn Trace>> {
    Ok(parse_contour_data(ct_obj, context)?)
}