pulldown_latex/
config.rs

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