1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
//! Configuration options for the renderer.
//!
//! The configuration of the `mathml` renderer is done through the [`RenderConfig`] struct.
use std::fmt::Display;
/// Configuration for the `mathml` renderer.
///
/// The default value is: [`RenderConfig::default`].
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RenderConfig<'a> {
    /// See [`DisplayMode`].
    pub display_mode: DisplayMode,
    /// If Some, the `mathml` generated includes an `<annotation>` element that contains the
    /// provided string. It is commonly used to include the LaTeX source code in the generated `mathml`.
    pub annotation: Option<&'a str>,
    /// A RGB color. This option determines the color in which errors and invalid LaTeX commands are rendered in.
    pub error_color: (u8, u8, u8),
    /// If true, a `xml` namespace (`xmlns="http://www.w3.org/1998/Math/MathML"`) will be written
    /// into the `<math>` element.
    ///
    /// This namespace is unnecessary for modern browsers but can be helpful for other user agents,
    /// such as Microsoft Word.
    pub xml: bool,
    /// See [`MathStyle`].
    pub math_style: MathStyle,
}
impl<'a> RenderConfig<'a> {
    /// Create a new `RenderConfig` with the provided annotation, and default values for other fields.
    pub fn with_annotation(annotation: &'a str) -> Self {
        Self {
            annotation: Some(annotation),
            ..Self::default()
        }
    }
}
impl<'a> Default for RenderConfig<'a> {
    /// # Default Value
    /// ```rust
    /// # use pulldown_latex::config::{RenderConfig, DisplayMode, MathStyle};
    /// const DEFAULT: RenderConfig = RenderConfig {
    ///     display_mode: DisplayMode::Inline,
    ///     annotation: None,
    ///     error_color: (178, 34, 34),
    ///     xml: false,
    ///     math_style: MathStyle::TeX,
    /// };
    /// assert_eq!(RenderConfig::default(), DEFAULT);
    /// ```
    fn default() -> Self {
        Self {
            display_mode: DisplayMode::Inline,
            annotation: None,
            error_color: (178, 34, 34),
            xml: false,
            math_style: MathStyle::TeX,
        }
    }
}
/// The way in which math variables are displayed.
///
/// This is used to determine how single-letter variables are displayed. This affects lowercase and
/// uppercase latin letters (__a-z__ and __A-Z__), and uppercase and lowercase greek letters
/// (__α-ω__ and __Α-Ω__). Style differences are shown in the table below.
///
/// ## Math Styles
///
/// | Style     | Low. Latin | Upp. Latin | Low. Greek | Upp. Greek |
/// | -----     | ---------- | ---------- | ---------- | ---------- |
/// | `TeX`     | _italic_   | _italic_   | _italic_   | upright    |
/// | `ISO`     | _italic_   | _italic_   | _italic_   | _italic_   |
/// | `French`  | _italic_   | upright    | upright    | upright    |
/// | `Upright` | upright    | upright    | upright    | upright    |
///
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub enum MathStyle {
    /// The default style used in TeX.
    ///
    /// Makes everything italic except for uppercase greek letters.
    ///
    /// __This is the default value.__
    #[default]
    TeX,
    /// The style used in `ISO 80000-2:2019`.
    ///
    /// Makes everything italic.
    ISO,
    /// The style used in French typography.
    ///
    /// Makes everything upright except for lowercase latin letters.
    French,
    /// Makes everything upright.
    Upright,
}
impl MathStyle {
    /// Whether or not the style should __manually__ be set to upright for the given character.
    ///
    /// The mathml spec states that the default style for math variables is italic for all
    /// characters, following the ISO 80000-2:2019 standard. If the style is set to something other
    /// than `TeX`, then the style should be set to upright for some characters. This function
    /// returns `true` if the style should be set to upright for the given character.
    pub(crate) fn should_be_upright(self, c: char) -> bool {
        match self {
            MathStyle::TeX => c.is_uppercase() && !c.is_ascii_uppercase(),
            MathStyle::ISO => false,
            MathStyle::French => !c.is_ascii_lowercase(),
            MathStyle::Upright => true,
        }
    }
}
/// How the math is displayed.
///
/// Semantically, this affects the [`display`] attribute of the [`<math>`] tag in the mathml
/// output. The attribute will be set to `block` or `inline` depending on the value of this enum.
///
/// [`<math>`]: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/math
/// [`display`]: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/math#display
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum DisplayMode {
    /// The math is rendered inline.
    ///
    /// The equation is displayed inline within a sentence or paragraph, and elements such as
    /// `\int` and `\sum` are minimized to fit within the line.
    ///
    /// __This is the default value.__
    #[default]
    Inline,
    /// The math is rendered in display/block mode (`displaystyle` in LaTeX).
    ///
    /// The equation is centered on its own line
    /// and elements such as`\int` and `\sum` are displayed bigger.
    Block,
}
impl Display for DisplayMode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            DisplayMode::Inline => f.write_str("inline"),
            DisplayMode::Block => f.write_str("block"),
        }
    }
}