katex/parser/parse_node.rs
1//! Parse node type definitions for KaTeX AST representation
2//!
3//! This module contains the Rust equivalents of the JavaScript Flow type
4//! definitions for parse nodes, which form the core of KaTeX's Abstract Syntax
5//! Tree (AST).
6
7use crate::build_html::DomType;
8use crate::spacing_data::MeasurementOwned;
9use crate::style::Style;
10use crate::symbols::Atom;
11use crate::types::{Mode, SourceLocation, Token};
12
13use crate::namespace::KeyMap;
14use strum::{AsRefStr, Display, EnumDiscriminants};
15use thiserror::Error;
16
17/// Represents the different types of column separation used in array
18/// environments within LaTeX/KaTeX mathematical expressions.
19///
20/// This enum defines the various alignment and separation styles that can be
21/// applied to columns in array-like structures, such as matrices or tables in
22/// mathematical typesetting. Each variant corresponds to a specific LaTeX array
23/// column type and influences how spacing and alignment are handled during
24/// rendering.
25///
26/// # Examples
27///
28/// In LaTeX source:
29/// ```latex
30/// \begin{pmatrix} a & b \\ c & d \end{pmatrix} // Uses Align or Gather
31/// \begin{alignat}{2} x &= 1 \\ y &= 2 \end{alignat} // Uses Alignat
32/// ```
33///
34/// # Usage
35///
36/// Used internally by the parser when constructing [`ParseNodeArray`] nodes to
37/// specify how columns should be separated and aligned. The choice affects
38/// spacing calculations and rendering behavior in the final output.
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum ColSeparationType {
41 /// Standard alignment with default spacing, typically centered columns
42 Align,
43 /// Alignment with specific left/right positioning, often used for equation
44 /// arrays
45 Alignat,
46 /// Gathering style with centered columns and appropriate spacing
47 Gather,
48 /// Compact spacing for dense arrays
49 Small,
50 /// Special handling for commutative diagram environments
51 CD,
52}
53
54/// Specifies the alignment and spacing properties for individual columns in
55/// array environments.
56///
57/// This enum provides detailed control over how each column in a mathematical
58/// array (matrix, table, etc.) should be aligned and spaced. It supports both
59/// simple separator-based alignment and more complex alignment specifications
60/// with custom gaps.
61///
62/// # Usage
63///
64/// Used in [`ParseNodeArray`] to define column properties. The alignment
65/// affects how mathematical expressions are positioned within each cell of the
66/// array structure.
67#[derive(Debug, Clone, PartialEq)]
68pub enum AlignSpec {
69 /// Simple alignment using a separator string (e.g., "|", ":", etc.)
70 Separator {
71 /// The string used to separate or align the column (e.g., "|", ":",
72 /// etc.)
73 separator: String,
74 },
75 /// Advanced alignment with custom spacing
76 Align {
77 /// The alignment string (e.g., "c", "l", "r" for center/left/right)
78 align: String,
79 /// Optional space before the column content (in em units)
80 pregap: Option<f64>,
81 /// Optional space after the column content (in em units)
82 postgap: Option<f64>,
83 },
84}
85
86/// The core Abstract Syntax Tree (AST) node type for KaTeX mathematical
87/// expressions.
88///
89/// This enum represents all possible parse nodes that can appear in a parsed
90/// LaTeX/KaTeX mathematical expression. Each variant corresponds to a specific
91/// type of mathematical construct, from simple symbols to complex structures
92/// like arrays and fractions.
93///
94/// The AST is built during parsing and represents the hierarchical structure of
95/// mathematical expressions, which is then used for rendering and further
96/// processing.
97///
98/// # Architecture
99///
100/// The enum uses the `strum` crate for discriminant generation, allowing
101/// runtime type checking and serialization. The [`NodeType`] discriminant
102/// provides a way to identify node types without pattern matching.
103///
104/// # Usage
105///
106/// Parse nodes are typically created by the parser from LaTeX input and then
107/// processed by the rendering engine. They can be traversed, transformed, and
108/// analyzed using the provided utility functions.
109///
110/// # See Also
111///
112/// * [`NodeType`] - The discriminant type for runtime type checking
113/// * [`assert_node_type`] - Type assertion utility
114/// * [`ParseNode`] - Type alias for this enum
115#[derive(Debug, Clone, PartialEq, EnumDiscriminants)]
116#[strum_discriminants(vis(pub))]
117#[strum_discriminants(doc = "Discriminant type for runtime type checking of parse nodes")]
118#[strum_discriminants(derive(Display, Hash, AsRefStr), strum(serialize_all = "lowercase"))]
119#[strum_discriminants(name(NodeType))]
120pub enum AnyParseNode {
121 /// ## Structural Nodes
122 /// Array/matrix environments with rows and columns
123 Array(ParseNodeArray),
124 /// Ordered groups of expressions (parentheses, etc.)
125 OrdGroup(ParseNodeOrdGroup),
126 /// Superscript/subscript combinations
127 SupSub(ParseNodeSupSub),
128 /// Generalized fractions (fractions, binomials)
129 Genfrac(Box<ParseNodeGenfrac>),
130 /// Left-right delimiter pairs
131 LeftRight(ParseNodeLeftRight),
132 #[strum_discriminants(strum(serialize = "leftright-right"))]
133 /// Right delimiters in left-right delimiter pairs (\left...\right).
134 LeftRightRight(ParseNodeLeftRightRight),
135 /// Square roots and nth roots
136 Sqrt(Box<ParseNodeSqrt>),
137
138 /// ## Symbol Nodes
139 /// Atomic symbols with specific mathematical meaning
140 Atom(ParseNodeAtom),
141 /// Ordinary mathematical symbols
142 MathOrd(ParseNodeMathOrd),
143 /// Mathematical operators
144 Op(ParseNodeOp),
145 /// Explicit spacing elements
146 Spacing(ParseNodeSpacing),
147
148 /// ## Text and Styling
149 /// Text content within math
150 Text(ParseNodeText),
151 /// Style changes (bold, italic, etc.)
152 Styling(ParseNodeStyling),
153 /// Font family changes
154 Font(ParseNodeFont),
155 /// Color specifications
156 Color(ParseNodeColor),
157
158 /// ## Functions and Commands
159 /// Accents over symbols (hats, bars, etc.)
160 Accent(Box<ParseNodeAccent>),
161 /// Horizontal lines on top of expressions
162 Overline(ParseNodeOverline),
163 /// Horizontal lines below expressions
164 Underline(ParseNodeUnderline),
165 /// Invisible content for spacing or alignment
166 Phantom(ParseNodePhantom),
167 /// Horizontal phantom content for spacing (\hphantom{...}).
168 Hphantom(ParseNodeHphantom),
169 /// Vertical phantom content for spacing (\vphantom{...}).
170 Vphantom(ParseNodeVphantom),
171 /// Horizontal/vertical rules
172 Rule(ParseNodeRule),
173
174 /// ## Miscellaneous Nodes
175 /// Labels for arrows in commutative diagram environments
176 /// (\begin{CD}...\end{CD}).
177 CdLabel(ParseNodeCdLabel),
178 /// Parent containers for CD labels in commutative diagrams.
179 CdLabelParent(ParseNodeCdLabelParent),
180 #[strum_discriminants(strum(serialize = "color-token"))]
181 /// Color tokens for setting current color context (\color{name}).
182 ColorToken(ParseNodeColorToken),
183 /// Raw content passed through without mathematical processing.
184 Raw(ParseNodeRaw),
185 /// Size specifications for spacing and dimensions (\rule, spacing
186 /// commands).
187 Size(ParseNodeSize),
188 /// Tagged equations with labels (\tag{label} or automatic numbering).
189 Tag(ParseNodeTag),
190 /// Hyperlinks in mathematical expressions (\url{...}).
191 Url(ParseNodeUrl),
192 /// Verbatim text preserving exact formatting (\verb|text| or
193 /// \begin{verbatim}...\end{verbatim}).
194 Verb(ParseNodeVerb),
195 /// Ordinary text symbols in math mode (letters, punctuation).
196 TextOrd(ParseNodeTextOrd),
197 #[strum_discriminants(strum(serialize = "accent-token"))]
198 /// Accent symbols for diacritical marks (\hat, \bar, \tilde, etc.).
199 AccentToken(ParseNodeAccentToken),
200 #[strum_discriminants(strum(serialize = "op-token"))]
201 /// Operator symbols with special positioning (\sum, \int, \lim, etc.).
202 OpToken(ParseNodeOpToken),
203 #[strum_discriminants(strum(serialize = "accentUnder"))]
204 /// Accent marks placed below expressions (\underline, \underbar, etc.).
205 AccentUnder(Box<ParseNodeAccentUnder>),
206 /// Carriage returns and line breaks (\\, \newline).
207 Cr(ParseNodeCr),
208 /// Delimiter sizing for proper enclosure (\big, \Big, \bigg, etc.).
209 Delimsizing(ParseNodeDelimsizing),
210 /// Enclosed expressions with styling (\boxed, \colorbox, etc.).
211 Enclose(ParseNodeEnclose),
212 /// Custom mathematical environments (\begin{env}...\end{env}).
213 Environment(Box<ParseNodeEnvironment>),
214 /// Horizontal boxes for grouping content (\hbox{...}).
215 Hbox(ParseNodeHbox),
216 /// Horizontal braces above/below expressions (\overbrace, \underbrace).
217 HorizBrace(ParseNodeHorizBrace),
218 /// Hyperlinks with custom text (\href{url}{text}).
219 Href(ParseNodeHref),
220 /// Embedded HTML content within math expressions.
221 Html(ParseNodeHtml),
222 /// Content renderable in both HTML and MathML formats.
223 HtmlMathMl(ParseNodeHtmlMathMl),
224 /// Included graphics/images (\includegraphics{...}).
225 Includegraphics(ParseNodeIncludegraphics),
226 /// Custom infix operators between operands.
227 Infix(ParseNodeInfix),
228 /// Internal parser nodes for implementation details.
229 Internal(ParseNodeInternal),
230 /// Explicit kerning/spacing adjustments (\kern, \mkern).
231 Kern(ParseNodeKern),
232 /// Overlapping content for annotations (\rlap, \llap, \clap).
233 Lap(ParseNodeLap),
234 /// Different renderings for display/text/script modes
235 /// (\mathchoice{...}{...}{...}{...}).
236 MathChoice(ParseNodeMathChoice),
237 /// Middle delimiters in expressions (\middle|).
238 Middle(ParseNodeMiddle),
239 /// Math class specifications for spacing and rendering (mord, mbin, mrel,
240 /// etc.).
241 Mclass(ParseNodeMclass),
242 /// Operator names with special formatting (\operatorname{...}).
243 OperatorName(ParseNodeOperatorName),
244 /// Poor man's bold text formatting (\pmb{...}).
245 Pmb(ParseNodePmb),
246 /// Raised or lowered content (\raisebox{...}{...}).
247 Raisebox(ParseNodeRaisebox),
248 /// Size changes for expressions (\scriptsize, \large, etc.).
249 Sizing(ParseNodeSizing),
250 /// Smashed content ignoring height/depth (\smash{...}).
251 Smash(ParseNodeSmash),
252 /// Vertically centered content (\vcenter{...}).
253 Vcenter(ParseNodeVcenter),
254 #[strum_discriminants(strum(serialize = "x-arrow"))]
255 /// Extensible arrows with labels (\xleftarrow{...}, \xrightarrow{...}).
256 XArrow(ParseNodeXArrow),
257}
258
259impl AnyParseNode {
260 /// TeXbook algorithms often reference "character boxes", which are simply
261 /// groups with a single character in them. To decide if something is a
262 /// character box, we find its innermost group, and see if it is a
263 /// single character.
264 ///
265 /// This is equivalent to `utils.isCharacterBox` in the JS codebase.
266 pub fn is_character_box(&self) -> Result<bool, ParseNodeError> {
267 let base_elem = self.to_base_elem()?;
268 Ok(matches!(
269 base_elem,
270 Self::MathOrd { .. } | Self::TextOrd { .. } | Self::Atom { .. }
271 ))
272 }
273
274 /// Sometimes we want to pull out the innermost element of a group. In most
275 /// cases, this will just be the group itself, but when ordgroups and colors
276 /// have a single element, we want to pull that out.
277 ///
278 /// This is equivalent to `utils.getBaseElem` in the JS codebase.
279 pub fn to_base_elem(&self) -> Result<&Self, ParseNodeError> {
280 match self {
281 Self::OrdGroup(ord) => {
282 if ord.body.len() == 1 {
283 ord.body[0].to_base_elem()
284 } else {
285 Ok(self)
286 }
287 }
288 Self::Color(color) => {
289 if color.body.len() == 1 {
290 color.body[0].to_base_elem()
291 } else {
292 Ok(self)
293 }
294 }
295 Self::Font(font) => font.body.to_base_elem(),
296 _ => Ok(self),
297 }
298 }
299
300 /// Get the mode of current node
301 #[must_use]
302 pub fn mode(&self) -> Mode {
303 match self {
304 Self::Array(node) => node.mode,
305 Self::OrdGroup(node) => node.mode,
306 Self::SupSub(node) => node.mode,
307 Self::Genfrac(node) => node.mode,
308 Self::LeftRight(node) => node.mode,
309 Self::LeftRightRight(node) => node.mode,
310 Self::Sqrt(node) => node.mode,
311 Self::Atom(node) => node.mode,
312 Self::MathOrd(node) => node.mode,
313 Self::Op(op) => match op {
314 ParseNodeOp::Symbol { mode, .. } | ParseNodeOp::Body { mode, .. } => *mode,
315 },
316 Self::Spacing(node) => node.mode,
317 Self::Text(node) => node.mode,
318 Self::Styling(node) => node.mode,
319 Self::Font(node) => node.mode,
320 Self::Color(node) => node.mode,
321 Self::Accent(node) => node.mode,
322 Self::Overline(node) => node.mode,
323 Self::Underline(node) => node.mode,
324 Self::Phantom(node) => node.mode,
325 Self::Hphantom(node) => node.mode,
326 Self::Vphantom(node) => node.mode,
327 Self::Rule(node) => node.mode,
328 Self::CdLabel(node) => node.mode,
329 Self::CdLabelParent(node) => node.mode,
330 Self::ColorToken(node) => node.mode,
331 Self::Raw(node) => node.mode,
332 Self::Size(node) => node.mode,
333 Self::Tag(node) => node.mode,
334 Self::Url(node) => node.mode,
335 Self::Verb(node) => node.mode,
336 Self::TextOrd(node) => node.mode,
337 Self::AccentToken(node) => node.mode,
338 Self::OpToken(node) => node.mode,
339 Self::AccentUnder(node) => node.mode,
340 Self::Cr(node) => node.mode,
341 Self::Delimsizing(node) => node.mode,
342 Self::Enclose(node) => node.mode,
343 Self::Environment(node) => node.mode,
344 Self::Hbox(node) => node.mode,
345 Self::HorizBrace(node) => node.mode,
346 Self::Href(node) => node.mode,
347 Self::Html(node) => node.mode,
348 Self::HtmlMathMl(node) => node.mode,
349 Self::Includegraphics(node) => node.mode,
350 Self::Infix(node) => node.mode,
351 Self::Internal(node) => node.mode,
352 Self::Kern(node) => node.mode,
353 Self::Lap(node) => node.mode,
354 Self::MathChoice(node) => node.mode,
355 Self::Middle(node) => node.mode,
356 Self::Mclass(node) => node.mode,
357 Self::OperatorName(node) => node.mode,
358 Self::Pmb(node) => node.mode,
359 Self::Raisebox(node) => node.mode,
360 Self::Sizing(node) => node.mode,
361 Self::Smash(node) => node.mode,
362 Self::Vcenter(node) => node.mode,
363 Self::XArrow(node) => node.mode,
364 }
365 }
366
367 /// Get the text field of the node
368 ///
369 /// `checkSymbolNodeType` checks if the node is a symbol and returns its
370 /// text later in Javascript.
371 #[must_use]
372 pub fn text(&self) -> Option<&str> {
373 match self {
374 // Atom
375 Self::Atom(node) => Some(&node.text),
376 // Non-Atom
377 Self::AccentToken(node) => Some(&node.text),
378 Self::MathOrd(node) => Some(&node.text),
379 Self::OpToken(node) => Some(&node.text),
380 Self::Spacing(node) => Some(&node.text),
381 Self::TextOrd(node) => Some(&node.text),
382 _ => None,
383 }
384 }
385
386 /// Get the label field of the node
387 #[must_use]
388 pub fn label(&self) -> Option<&str> {
389 match self {
390 Self::Accent(acc) => Some(&acc.label),
391 Self::AccentUnder(acc_under) => Some(&acc_under.label),
392 Self::HorizBrace(hb) => Some(&hb.label),
393 Self::XArrow(xa) => Some(&xa.label),
394 Self::Enclose(enclose) => Some(&enclose.label),
395 _ => None,
396 }
397 }
398}
399
400/// The array item of tags in array
401#[derive(Debug, Clone, PartialEq)]
402pub enum ParseNodeArrayTag {
403 /// A boolean value indicating if the tag is active
404 Bool(bool),
405 /// A list of nodes associated with the tag
406 Nodes(Vec<AnyParseNode>),
407}
408
409impl From<Vec<AnyParseNode>> for ParseNodeArrayTag {
410 fn from(nodes: Vec<AnyParseNode>) -> Self {
411 Self::Nodes(nodes)
412 }
413}
414
415impl From<bool> for ParseNodeArrayTag {
416 fn from(b: bool) -> Self {
417 Self::Bool(b)
418 }
419}
420
421impl ParseNodeArrayTag {
422 /// If is true or has nodes
423 #[must_use]
424 pub const fn is_true(&self) -> bool {
425 match self {
426 Self::Bool(b) => *b,
427 // In Javascript, `[]` is true
428 Self::Nodes(_) => true,
429 }
430 }
431}
432
433/// Represents array and matrix environments in mathematical expressions.
434///
435/// This struct handles the parsing and representation of array-like structures
436/// such as matrices, tables, and aligned equations in LaTeX/KaTeX. It supports
437/// various column alignments, spacing, and formatting options.
438///
439/// # LaTeX Correspondence
440///
441/// Corresponds to LaTeX environments like:
442/// ```latex
443/// \begin{pmatrix} a & b \\ c & d \end{pmatrix} % Matrix
444/// \begin{array}{cc} a & b \\ c & d \end{array} % General array
445/// \begin{align} x &= 1 \\ y &= 2 \end{align} % Aligned equations
446/// ```
447///
448/// # Usage
449///
450/// Arrays are fundamental for representing matrices, systems of equations, and
451/// tabular data in mathematical typesetting. The parser creates these nodes
452/// when encountering array environments.
453#[derive(Debug, Clone, PartialEq)]
454pub struct ParseNodeArray {
455 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
456 pub mode: Mode,
457 /// Optional source location for error reporting
458 pub loc: Option<SourceLocation>,
459 /// Type of column separation ([`ColSeparationType`])
460 pub col_separation_type: Option<ColSeparationType>,
461 /// Whether to add horizontal skip before/after the array
462 pub hskip_before_and_after: Option<bool>,
463 /// Whether to add extra vertical spacing between rows
464 pub add_jot: Option<bool>,
465 /// Column alignment specifications ([`AlignSpec`])
466 pub cols: Option<Vec<AlignSpec>>,
467 /// Vertical stretching factor for the array
468 pub arraystretch: f64,
469 /// The array content as a vector of rows, each containing cells
470 pub body: Vec<Vec<AnyParseNode>>,
471 /// Vertical gaps between rows
472 pub row_gaps: Vec<Option<MeasurementOwned>>,
473 /// Horizontal lines to draw before each row
474 pub h_lines_before_row: Vec<Vec<bool>>,
475 /// Optional equation tags/numbers for each row
476 pub tags: Option<Vec<ParseNodeArrayTag>>,
477 /// Whether to place equation numbers on the left
478 pub leqno: Option<bool>,
479 /// Whether this is a commutative diagram array
480 pub is_cd: Option<bool>,
481}
482
483/// Represents labels in commutative diagram (CD) environments.
484///
485/// This struct handles labels attached to arrows or objects in commutative
486/// diagrams, which are specialized mathematical diagrams showing relationships
487/// between objects.
488///
489/// # Fields
490///
491/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
492/// * `loc` - Optional source location for error reporting
493/// * `side` - The side of the arrow/object where the label appears ("top",
494/// "bottom", "left", "right")
495/// * `label` - The mathematical expression serving as the label
496///
497/// # LaTeX Correspondence
498///
499/// Used in CD environments:
500/// ```latex
501/// \begin{CD}
502/// A @>f>> B
503/// @VVgV @VVhV
504/// C @>>k> D
505/// \end{CD}
506/// ```
507///
508/// # Usage
509///
510/// CD labels provide annotations for arrows and objects in commutative
511/// diagrams, helping to clarify the mathematical relationships being depicted.
512#[derive(Debug, Clone, PartialEq)]
513pub struct ParseNodeCdLabel {
514 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
515 pub mode: Mode,
516 /// Optional source location for error reporting
517 pub loc: Option<SourceLocation>,
518 /// The side of the arrow/object where the label appears ("top", "bottom",
519 /// "left", "right")
520 pub side: String,
521 /// The mathematical expression serving as the label
522 pub label: Box<AnyParseNode>,
523}
524
525/// Represents parent containers for CD labels in commutative diagrams.
526///
527/// This struct serves as a wrapper for fragments that contain CD labels,
528/// maintaining the hierarchical structure of commutative diagram elements.
529///
530/// # Fields
531///
532/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
533/// * `loc` - Optional source location for error reporting
534/// * `fragment` - The contained mathematical expression or diagram fragment
535///
536/// # Usage
537///
538/// Used internally to maintain proper nesting and structure in commutative
539/// diagram parsing. The fragment typically contains the arrow or object being
540/// labeled.
541#[derive(Debug, Clone, PartialEq)]
542pub struct ParseNodeCdLabelParent {
543 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
544 pub mode: Mode,
545 /// Optional source location for error reporting
546 pub loc: Option<SourceLocation>,
547 /// The contained mathematical expression or diagram fragment
548 pub fragment: Box<AnyParseNode>,
549}
550
551/// Represents color changes applied to mathematical expressions.
552///
553/// This struct wraps mathematical content with color specifications, allowing
554/// different parts of expressions to be rendered in different colors.
555///
556/// # Fields
557///
558/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
559/// * `loc` - Optional source location for error reporting
560/// * `color` - The color specification (name, hex code, or RGB values)
561/// * `body` - The mathematical expressions to be colored
562///
563/// # LaTeX Correspondence
564///
565/// Corresponds to LaTeX color commands:
566/// ```latex
567/// \color{red}{x + y}
568/// {\color{blue} \frac{a}{b}}
569/// ```
570///
571/// # Usage
572///
573/// Color nodes allow visual distinction of different parts of mathematical
574/// expressions, useful for highlighting important terms or distinguishing
575/// different variables.
576#[derive(Debug, Clone, PartialEq)]
577pub struct ParseNodeColor {
578 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
579 pub mode: Mode,
580 /// Optional source location for error reporting
581 pub loc: Option<SourceLocation>,
582 /// The color specification (name, hex code, or RGB values)
583 pub color: String,
584 /// The mathematical expressions to be colored
585 pub body: Vec<AnyParseNode>,
586}
587
588impl From<ParseNodeColor> for AnyParseNode {
589 fn from(node: ParseNodeColor) -> Self {
590 Self::Color(node)
591 }
592}
593
594/// Represents color tokens in mathematical expressions.
595///
596/// This struct handles standalone color specifications that don't wrap content,
597/// typically used for setting the current color context.
598///
599/// # Fields
600///
601/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
602/// * `loc` - Optional source location for error reporting
603/// * `color` - The color specification string
604///
605/// # Usage
606///
607/// Used for color commands that set the current color without immediately
608/// applying it to content, allowing subsequent expressions to inherit the
609/// color.
610#[derive(Debug, Clone, PartialEq, Eq)]
611pub struct ParseNodeColorToken {
612 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
613 pub mode: Mode,
614 /// Optional source location for error reporting
615 pub loc: Option<SourceLocation>,
616 /// The color specification string
617 pub color: String,
618}
619
620/// Represents mathematical operators in KaTeX expressions, supporting both
621/// symbolic and compound operators.
622///
623/// This enum handles operators that can appear in mathematical expressions,
624/// including those with limits (subscripts/superscripts above/below) and those
625/// that contain other expressions as their body.
626///
627/// # Usage
628///
629/// Used for operators like `\sum`, `\int`, `\lim`, etc. The `limits` field
630/// controls whether sub/super scripts appear as limits (above/below) or as
631/// regular scripts (right side).
632///
633/// # LaTeX Examples
634///
635/// ```latex
636/// \sum_{i=1}^{n} x_i % limits = true
637/// \int_a^b f(x) dx % limits = false (default)
638/// \lim_{x \to 0} f(x) % limits = true
639/// ```
640#[derive(Debug, Clone, PartialEq)]
641pub enum ParseNodeOp {
642 /// A simple operator symbol with optional limit positioning
643 Symbol {
644 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
645 mode: Mode,
646 /// Optional source location for error reporting
647 loc: Option<SourceLocation>,
648 /// Whether limits should be displayed above/below (true) or as
649 /// sub/super scripts (false)
650 limits: bool,
651 /// Force special handling of adjacent superscripts/subscripts
652 always_handle_sup_sub: Option<bool>,
653 /// Suppress vertical shifting of the base symbol
654 suppress_base_shift: Option<bool>,
655 /// Whether this operator is part of a sup/sub script context
656 parent_is_sup_sub: bool,
657 /// The operator name/symbol (e.g., "sum", "lim", "int")
658 name: String,
659 /// Whether it is a symbol
660 symbol: bool,
661 },
662 /// An operator that contains other expressions as its body
663 Body {
664 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
665 mode: Mode,
666 /// Optional source location for error reporting
667 loc: Option<SourceLocation>,
668 /// Whether limits should be displayed above/below (true) or as
669 /// sub/super scripts (false)
670 limits: bool,
671 /// Force special handling of adjacent superscripts/subscripts
672 always_handle_sup_sub: Option<bool>,
673 /// Suppress vertical shifting of the base symbol
674 suppress_base_shift: Option<bool>,
675 /// Whether this operator is part of a sup/sub script context
676 parent_is_sup_sub: bool,
677 /// The expressions that form the operator's content
678 body: Vec<AnyParseNode>,
679 },
680}
681
682impl ParseNodeOp {
683 /// Get the limits field
684 #[must_use]
685 pub const fn limits(&self) -> bool {
686 match self {
687 Self::Symbol { limits, .. } | Self::Body { limits, .. } => *limits,
688 }
689 }
690
691 /// Mutate the limits field
692 #[must_use]
693 pub const fn limits_mut(&mut self) -> &mut bool {
694 match self {
695 Self::Symbol { limits, .. } | Self::Body { limits, .. } => limits,
696 }
697 }
698
699 /// Get the always_handle_sup_sub field
700 #[must_use]
701 pub fn always_handle_sup_sub(&self) -> bool {
702 let field = match self {
703 Self::Symbol {
704 always_handle_sup_sub,
705 ..
706 }
707 | Self::Body {
708 always_handle_sup_sub,
709 ..
710 } => *always_handle_sup_sub,
711 };
712 field.unwrap_or(false)
713 }
714
715 /// Mutate the always_handle_sup_sub field
716 #[must_use]
717 pub const fn always_handle_sup_sub_mut(&mut self) -> &mut Option<bool> {
718 match self {
719 Self::Symbol {
720 always_handle_sup_sub,
721 ..
722 }
723 | Self::Body {
724 always_handle_sup_sub,
725 ..
726 } => always_handle_sup_sub,
727 }
728 }
729
730 /// Get the name field
731 #[must_use]
732 pub fn name(&self) -> Option<&str> {
733 match self {
734 Self::Symbol { name, .. } => Some(name),
735 Self::Body { .. } => None,
736 }
737 }
738}
739
740/// Represents ordered groups of mathematical expressions, typically enclosed in
741/// parentheses or brackets.
742///
743/// This struct handles grouped expressions that should be treated as a single
744/// unit, such as parenthesized subexpressions or bracketed terms.
745///
746/// # Fields
747///
748/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
749/// * `loc` - Optional source location for error reporting
750/// * `body` - The expressions contained within the group
751/// * `semisimple` - Whether this is a simple grouping (affects spacing and
752/// rendering)
753///
754/// # LaTeX Correspondence
755///
756/// Corresponds to grouped expressions:
757/// ```latex
758/// (x + y) % Parentheses
759/// {a + b} % Braces
760/// [c + d] % Brackets
761/// ```
762///
763/// # Usage
764///
765/// OrdGroups ensure proper precedence and grouping in mathematical expressions,
766/// affecting both parsing order and visual rendering with appropriate
767/// delimiters.
768#[derive(Debug, Clone, PartialEq)]
769pub struct ParseNodeOrdGroup {
770 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
771 pub mode: Mode,
772 /// Optional source location for error reporting
773 pub loc: Option<SourceLocation>,
774 /// The expressions contained within the group
775 pub body: Vec<AnyParseNode>,
776 /// Whether this is a simple grouping (affects spacing and rendering)
777 pub semisimple: Option<bool>,
778}
779
780/// Represents raw, unprocessed content in mathematical expressions.
781///
782/// This struct contains literal text or content that should be passed through
783/// without further mathematical processing or rendering.
784///
785/// # Fields
786///
787/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
788/// * `loc` - Optional source location for error reporting
789/// * `string` - The raw string content
790///
791/// # Usage
792///
793/// Used for content that needs to be preserved exactly as-is, such as
794/// literal text within math mode or special formatting commands.
795#[derive(Debug, Clone, PartialEq, Eq)]
796pub struct ParseNodeRaw {
797 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
798 pub mode: Mode,
799 /// Optional source location for error reporting
800 pub loc: Option<SourceLocation>,
801 /// The raw string content
802 pub string: String,
803}
804
805/// Represents size specifications for spacing or dimensions in mathematical
806/// expressions.
807///
808/// This struct handles explicit size measurements used for spacing, rules, or
809/// other dimensional elements in mathematical typesetting.
810///
811/// # Fields
812///
813/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
814/// * `loc` - Optional source location for error reporting
815/// * `value` - The size measurement ([`MeasurementOwned`])
816/// * `is_blank` - Whether this represents a blank/zero size
817///
818/// # Usage
819///
820/// Size nodes control the dimensions of various elements like rules, spacing,
821/// and other measurable components in mathematical layouts.
822#[derive(Debug, Clone, PartialEq)]
823pub struct ParseNodeSize {
824 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
825 pub mode: Mode,
826 /// Optional source location for error reporting
827 pub loc: Option<SourceLocation>,
828 /// The size measurement ([`MeasurementOwned`])
829 pub value: MeasurementOwned,
830 /// Whether this represents a blank/zero size
831 pub is_blank: bool,
832}
833
834/// Represents style changes applied to mathematical expressions.
835///
836/// This struct wraps mathematical content with style specifications like bold,
837/// italic, or other text styling attributes.
838///
839/// # Fields
840///
841/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
842/// * `loc` - Optional source location for error reporting
843/// * `style` - The style specification ([`Style`])
844/// * `body` - The expressions to be styled
845///
846/// # LaTeX Correspondence
847///
848/// Corresponds to LaTeX styling commands:
849/// ```latex
850/// \mathbf{x} % Bold
851/// \mathit{f} % Italic
852/// \mathrm{dx} % Roman/upright
853/// ```
854///
855/// # Usage
856///
857/// Styling nodes allow different visual appearances for mathematical symbols,
858/// useful for distinguishing vectors from scalars or emphasizing certain terms.
859#[derive(Debug, Clone, PartialEq)]
860pub struct ParseNodeStyling {
861 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
862 pub mode: Mode,
863 /// Optional source location for error reporting
864 pub loc: Option<SourceLocation>,
865 /// The style specification ([`Style`])
866 pub style: &'static Style,
867 /// The expressions to be styled
868 pub body: Vec<AnyParseNode>,
869}
870
871/// Represents superscript and subscript combinations in mathematical
872/// expressions.
873///
874/// This struct handles the attachment of superscript and/or subscript
875/// expressions to a base expression, supporting complex nested structures.
876///
877/// # Fields
878///
879/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
880/// * `loc` - Optional source location for error reporting
881/// * `base` - The base expression being modified
882/// * `sup` - Optional superscript expression
883/// * `sub` - Optional subscript expression
884///
885/// # LaTeX Correspondence
886///
887/// Corresponds to LaTeX superscript/subscript syntax:
888/// ```latex
889/// x^2 % Superscript
890/// a_i % Subscript
891/// x^{n+1} % Complex superscript
892/// a_{i,j} % Complex subscript
893/// ```
894///
895/// # Usage
896///
897/// SupSub nodes are fundamental for mathematical notation, allowing expressions
898/// like exponents, indices, and other modifiers to be properly positioned
899/// relative to their base.
900#[derive(Debug, Clone, PartialEq)]
901pub struct ParseNodeSupSub {
902 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
903 pub mode: Mode,
904 /// Optional source location for error reporting
905 pub loc: Option<SourceLocation>,
906 /// The base expression being modified
907 pub base: Option<Box<AnyParseNode>>,
908 /// Optional superscript expression
909 pub sup: Option<Box<AnyParseNode>>,
910 /// Optional subscript expression
911 pub sub: Option<Box<AnyParseNode>>,
912}
913
914/// Represents tagged equations or expressions with labels.
915///
916/// This struct handles equation tags, numbers, or labels that are associated
917/// with mathematical expressions, typically for referencing.
918///
919/// # Fields
920///
921/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
922/// * `loc` - Optional source location for error reporting
923/// * `body` - The main mathematical expression
924/// * `tag` - The tag/label expressions
925///
926/// # LaTeX Correspondence
927///
928/// Corresponds to LaTeX equation tagging:
929/// ```latex
930/// \tag{1} E = mc^2
931/// \begin{equation}\label{eq:energy}
932/// E = mc^2
933/// \end{equation}
934/// ```
935///
936/// # Usage
937///
938/// Tag nodes enable equation numbering and referencing in mathematical
939/// documents, allowing readers to cite specific equations.
940#[derive(Debug, Clone, PartialEq)]
941pub struct ParseNodeTag {
942 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
943 pub mode: Mode,
944 /// Optional source location for error reporting
945 pub loc: Option<SourceLocation>,
946 /// The main mathematical expression
947 pub body: Vec<AnyParseNode>,
948 /// The tag/label expressions
949 pub tag: Vec<AnyParseNode>,
950}
951
952/// Represents text content within mathematical expressions.
953///
954/// This struct handles text that appears in math mode, with optional font
955/// specifications for proper rendering of textual elements in mathematical
956/// contexts.
957///
958/// # Fields
959///
960/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
961/// * `loc` - Optional source location for error reporting
962/// * `body` - The text content as parse nodes
963/// * `font` - Optional font family specification
964///
965/// # LaTeX Correspondence
966///
967/// Corresponds to LaTeX text commands in math:
968/// ```latex
969/// \text{if} % Text in math
970/// \mathrm{dx} % Roman font
971/// \mathbf{v} % Bold font
972/// ```
973///
974/// # Usage
975///
976/// Text nodes allow mixing of textual and mathematical content, ensuring
977/// proper font rendering for words and phrases within mathematical expressions.
978#[derive(Debug, Clone, PartialEq)]
979pub struct ParseNodeText {
980 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
981 pub mode: Mode,
982 /// Optional source location for error reporting
983 pub loc: Option<SourceLocation>,
984 /// The text content as parse nodes
985 pub body: Vec<AnyParseNode>,
986 /// Optional font family specification
987 pub font: Option<String>,
988}
989
990/// Represents URL links in mathematical expressions.
991///
992/// This struct handles hyperlinks within mathematical content, allowing
993/// mathematical expressions to contain clickable links.
994///
995/// # Fields
996///
997/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
998/// * `loc` - Optional source location for error reporting
999/// * `url` - The URL string
1000///
1001/// # LaTeX Correspondence
1002///
1003/// Corresponds to LaTeX hyperlink commands:
1004/// ```latex
1005/// \url{https://example.com}
1006/// \href{https://example.com}{link text}
1007/// ```
1008///
1009/// # Usage
1010///
1011/// URL nodes enable interactive mathematical documents with embedded links,
1012/// useful for referencing external resources or documentation.
1013#[derive(Debug, Clone, PartialEq, Eq)]
1014pub struct ParseNodeUrl {
1015 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1016 pub mode: Mode,
1017 /// Optional source location for error reporting
1018 pub loc: Option<SourceLocation>,
1019 /// The URL string
1020 pub url: String,
1021}
1022
1023/// Represents verbatim text content that should be rendered exactly as written.
1024///
1025/// This struct handles text that must preserve its exact formatting and
1026/// spacing, without any mathematical interpretation or processing.
1027///
1028/// # Fields
1029///
1030/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1031/// * `loc` - Optional source location for error reporting
1032/// * `body` - The verbatim text content
1033/// * `star` - Whether this is a starred version (affects rendering)
1034///
1035/// # LaTeX Correspondence
1036///
1037/// Corresponds to LaTeX verbatim commands:
1038/// ```latex
1039/// \verb|exact text|
1040/// \begin{verbatim}
1041/// exact text
1042/// \end{verbatim}
1043/// ```
1044///
1045/// # Usage
1046///
1047/// Verb nodes are essential for including code snippets, file paths, or other
1048/// text that must maintain exact spacing and special characters.
1049#[derive(Debug, Clone, PartialEq, Eq)]
1050pub struct ParseNodeVerb {
1051 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1052 pub mode: Mode,
1053 /// Optional source location for error reporting
1054 pub loc: Option<SourceLocation>,
1055 /// The verbatim text content
1056 pub body: String,
1057 /// Whether this is a starred version (affects rendering)
1058 pub star: bool,
1059}
1060
1061// Symbol parse nodes (from symbols.js)
1062
1063/// Represents atomic symbols with specific mathematical meaning and spacing
1064/// rules.
1065///
1066/// This struct handles individual symbols that have special significance in
1067/// mathematical typesetting, such as operators, relations, and other atomic
1068/// elements with defined spacing behavior.
1069///
1070/// # Fields
1071///
1072/// * `family` - The atom type ([`Atom`]) determining spacing and behavior
1073/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1074/// * `loc` - Optional source location for error reporting
1075/// * `text` - The symbol text
1076///
1077/// # Usage
1078///
1079/// Atoms are the fundamental building blocks of mathematical expressions,
1080/// with each atom type having specific spacing rules that affect layout.
1081#[derive(Debug, Clone, PartialEq, Eq)]
1082pub struct ParseNodeAtom {
1083 /// The atom type ([`Atom`]) determining spacing and behavior
1084 pub family: Atom,
1085 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1086 pub mode: Mode,
1087 /// Optional source location for error reporting
1088 pub loc: Option<SourceLocation>,
1089 /// The symbol text
1090 pub text: String,
1091}
1092
1093/// Represents ordinary mathematical symbols without special spacing rules.
1094///
1095/// This struct handles regular mathematical symbols that don't have special
1096/// spacing or positioning requirements, such as variables and digits.
1097///
1098/// # Fields
1099///
1100/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1101/// * `loc` - Optional source location for error reporting
1102/// * `text` - The symbol text
1103///
1104///
1105/// # LaTeX Correspondence
1106///
1107/// Corresponds to ordinary symbols in math mode:
1108/// ```latex
1109/// x y z % Variables
1110/// 1 2 3 % Digits
1111/// a b c % Letters
1112/// ```
1113///
1114/// # Usage
1115///
1116/// MathOrd nodes represent the most common type of mathematical symbols,
1117/// forming the basic content of expressions.
1118#[derive(Debug, Clone, PartialEq, Eq)]
1119pub struct ParseNodeMathOrd {
1120 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1121 pub mode: Mode,
1122 /// Optional source location for error reporting
1123 pub loc: Option<SourceLocation>,
1124 /// The symbol text
1125 pub text: String,
1126}
1127
1128/// Represents explicit spacing elements in mathematical expressions.
1129///
1130/// This struct handles manually inserted spacing that affects the layout
1131/// and positioning of mathematical elements.
1132///
1133/// # Fields
1134///
1135/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1136/// * `loc` - Optional source location for error reporting
1137/// * `text` - The spacing command or symbol
1138///
1139/// # LaTeX Correspondence
1140///
1141/// Corresponds to LaTeX spacing commands:
1142/// ```latex
1143/// \, % Thin space
1144/// \: % Medium space
1145/// \; % Thick space
1146/// \! % Negative thin space
1147/// ```
1148///
1149/// # Usage
1150///
1151/// Spacing nodes allow fine control over the horizontal spacing between
1152/// mathematical elements for proper visual appearance.
1153#[derive(Debug, Clone, PartialEq, Eq)]
1154pub struct ParseNodeSpacing {
1155 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1156 pub mode: Mode,
1157 /// Optional source location for error reporting
1158 pub loc: Option<SourceLocation>,
1159 /// The spacing command or symbol
1160 pub text: String,
1161}
1162
1163/// Represents ordinary text symbols within mathematical expressions.
1164///
1165/// This struct handles text characters that appear in math mode but don't
1166/// have mathematical symbol properties.
1167///
1168/// # Fields
1169///
1170/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1171/// * `loc` - Optional source location for error reporting
1172/// * `text` - The text content
1173///
1174/// # Usage
1175///
1176/// TextOrd nodes are used for text characters in mathematical contexts,
1177/// ensuring proper font and spacing treatment.
1178#[derive(Debug, Clone, PartialEq, Eq)]
1179pub struct ParseNodeTextOrd {
1180 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1181 pub mode: Mode,
1182 /// Optional source location for error reporting
1183 pub loc: Option<SourceLocation>,
1184 /// The text content
1185 pub text: String,
1186}
1187
1188/// Represents accent symbols used for diacritical marks.
1189///
1190/// This struct handles the symbol portion of accent commands,
1191/// which modify the appearance of base characters.
1192///
1193/// # Fields
1194///
1195/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1196/// * `loc` - Optional source location for error reporting
1197/// * `text` - The accent symbol
1198///
1199/// # LaTeX Correspondence
1200///
1201/// Corresponds to accent symbols:
1202/// ```latex
1203/// \hat{x} % ^
1204/// \bar{y} % -
1205/// \tilde{z} % ~
1206/// ```
1207///
1208/// # Usage
1209///
1210/// Accent tokens are combined with base characters to create accented symbols
1211/// in mathematical notation.
1212#[derive(Debug, Clone, PartialEq, Eq)]
1213pub struct ParseNodeAccentToken {
1214 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1215 pub mode: Mode,
1216 /// Optional source location for error reporting
1217 pub loc: Option<SourceLocation>,
1218 /// The accent symbol
1219 pub text: String,
1220}
1221
1222/// Represents operator symbols with special positioning rules.
1223///
1224/// This struct handles operator tokens that may have special rendering
1225/// requirements, such as limits positioning.
1226///
1227/// # Fields
1228///
1229/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1230/// * `loc` - Optional source location for error reporting
1231/// * `text` - The operator symbol
1232///
1233///
1234/// # Usage
1235///
1236/// OpTokens represent operators that may need special handling for
1237/// subscripts/superscripts (limits vs. regular scripts).
1238#[derive(Debug, Clone, PartialEq, Eq)]
1239pub struct ParseNodeOpToken {
1240 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1241 pub mode: Mode,
1242 /// Optional source location for error reporting
1243 pub loc: Option<SourceLocation>,
1244 /// The operator symbol
1245 pub text: String,
1246}
1247
1248// Function parse nodes (from functions/*.js)
1249
1250/// Represents accent marks placed above mathematical expressions.
1251///
1252/// This struct handles diacritical marks and accents that modify the appearance
1253/// of base mathematical expressions, such as hats, bars, and tildes.
1254///
1255/// # Fields
1256///
1257/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1258/// * `loc` - Optional source location for error reporting
1259/// * `label` - The accent symbol (e.g., "^", "-", "~")
1260/// * `is_stretchy` - Whether the accent stretches to fit the base width
1261/// * `is_shifty` - Whether the accent is shifted for better positioning
1262/// * `base` - The expression being accented
1263///
1264///
1265/// # LaTeX Correspondence
1266///
1267/// Corresponds to LaTeX accent commands:
1268/// ```latex
1269/// \hat{x} % Hat
1270/// \bar{y} % Bar
1271/// \tilde{z} % Tilde
1272/// \widehat{abc} % Wide hat
1273/// ```
1274///
1275/// # Usage
1276///
1277/// Accent nodes modify the visual appearance of mathematical symbols,
1278/// commonly used for vectors, complex numbers, and special notation.
1279#[derive(Debug, Clone, PartialEq)]
1280pub struct ParseNodeAccent {
1281 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1282 pub mode: Mode,
1283 /// Optional source location for error reporting
1284 pub loc: Option<SourceLocation>,
1285 /// The accent symbol (e.g., "^", "-", "~")
1286 pub label: String,
1287 /// Whether the accent stretches to fit the base width
1288 pub is_stretchy: Option<bool>,
1289 /// Whether the accent is shifted for better positioning
1290 pub is_shifty: Option<bool>,
1291 /// The expression being accented
1292 pub base: AnyParseNode,
1293}
1294
1295/// Represents accent marks placed below mathematical expressions.
1296///
1297/// This struct handles under-accents, which are diacritical marks positioned
1298/// beneath base expressions, such as underbars and undertildes.
1299///
1300/// # Fields
1301///
1302/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1303/// * `loc` - Optional source location for error reporting
1304/// * `label` - The under-accent symbol
1305/// * `is_stretchy` - Whether the accent stretches to fit the base width
1306/// * `is_shifty` - Whether the accent is shifted for better positioning
1307/// * `base` - The expression being under-accented
1308///
1309/// # LaTeX Correspondence
1310///
1311/// Corresponds to LaTeX under-accent commands:
1312/// ```latex
1313/// \underline{x} % Underline
1314/// \underbar{y} % Underbar
1315/// \utilde{z} % Undertilde
1316/// ```
1317///
1318/// # Usage
1319///
1320/// Under-accent nodes provide visual modifications below expressions,
1321/// useful for emphasis and special mathematical notation.
1322#[derive(Debug, Clone, PartialEq)]
1323pub struct ParseNodeAccentUnder {
1324 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1325 pub mode: Mode,
1326 /// Optional source location for error reporting
1327 pub loc: Option<SourceLocation>,
1328 /// The under-accent symbol
1329 pub label: String,
1330 /// Whether the accent stretches to fit the base width
1331 pub is_stretchy: Option<bool>,
1332 /// Whether the accent is shifted for better positioning
1333 pub is_shifty: Option<bool>,
1334 /// The expression being under-accented
1335 pub base: Box<AnyParseNode>,
1336}
1337
1338/// Represents carriage returns and line breaks in mathematical expressions.
1339///
1340/// This struct handles explicit line breaks and vertical spacing within
1341/// mathematical content, particularly in arrays and multiline constructs.
1342///
1343/// # Fields
1344///
1345/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1346/// * `loc` - Optional source location for error reporting
1347/// * `new_line` - Whether this represents a new line
1348/// * `size` - Optional size of the break ([`MeasurementOwned`])
1349///
1350/// # LaTeX Correspondence
1351///
1352/// Corresponds to LaTeX line break commands:
1353/// ```latex
1354/// \\ % Basic line break
1355/// \\[1em] % Line break with spacing
1356/// \newline % New line
1357/// ```
1358///
1359/// # Usage
1360///
1361/// CR nodes control line breaks in multiline mathematical expressions,
1362/// such as in arrays, cases, and aligned equations.
1363#[derive(Debug, Clone, PartialEq)]
1364pub struct ParseNodeCr {
1365 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1366 pub mode: Mode,
1367 /// Optional source location for error reporting
1368 pub loc: Option<SourceLocation>,
1369 /// Whether this represents a new line
1370 pub new_line: bool,
1371 /// Optional size of the break ([`MeasurementOwned`])
1372 pub size: Option<MeasurementOwned>,
1373}
1374
1375/// Represents delimiter sizing for mathematical symbols.
1376///
1377/// This struct handles the sizing of delimiters (parentheses, brackets, etc.)
1378/// to properly enclose mathematical expressions of varying heights.
1379///
1380/// # Fields
1381///
1382/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1383/// * `loc` - Optional source location for error reporting
1384/// * `size` - The size level (1-4, where 4 is largest)
1385/// * `mclass` - The math class ("mopen", "mclose", "mrel", "mord")
1386/// * `delim` - The delimiter symbol
1387///
1388///
1389/// # LaTeX Correspondence
1390///
1391/// Corresponds to LaTeX delimiter sizing:
1392/// ```latex
1393/// \big( % Size 2
1394/// \Big[ % Size 3
1395/// \bigg\{ % Size 4
1396/// \Bigg\langle % Size 5
1397/// ```
1398///
1399/// # Usage
1400///
1401/// Delimsizing nodes ensure delimiters scale appropriately to contain
1402/// their enclosed mathematical content.
1403#[derive(Debug, Clone, PartialEq, Eq)]
1404pub struct ParseNodeDelimsizing {
1405 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1406 pub mode: Mode,
1407 /// Optional source location for error reporting
1408 pub loc: Option<SourceLocation>,
1409 /// The size level (1-4, where 4 is largest)
1410 pub size: u8, // 1 | 2 | 3 | 4
1411 /// The math class ("mopen", "mclose", "mrel", "mord")
1412 pub mclass: DomType, // "mopen" | "mclose" | "mrel" | "mord"
1413 /// The delimiter symbol
1414 pub delim: String,
1415}
1416
1417/// Represents enclosed mathematical expressions with background and border
1418/// styling.
1419///
1420/// This struct handles expressions that are enclosed with colored backgrounds
1421/// or borders, often used for highlighting or special notation.
1422///
1423/// # Fields
1424///
1425/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1426/// * `loc` - Optional source location for error reporting
1427/// * `label` - The enclosure type/label
1428/// * `background_color` - Optional background color
1429/// * `border_color` - Optional border color
1430/// * `body` - The enclosed expression
1431///
1432///
1433/// # LaTeX Correspondence
1434///
1435/// Corresponds to LaTeX enclosure commands:
1436/// ```latex
1437/// \boxed{x} % Boxed
1438/// \colorbox{yellow}{x} % Background color
1439/// \fcolorbox{red}{blue}{x} % Border and background
1440/// ```
1441///
1442/// # Usage
1443///
1444/// Enclose nodes provide visual emphasis and grouping for mathematical
1445/// expressions, useful for highlighting important terms or creating visual
1446/// distinctions.
1447#[derive(Debug, Clone, PartialEq)]
1448pub struct ParseNodeEnclose {
1449 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1450 pub mode: Mode,
1451 /// Optional source location for error reporting
1452 pub loc: Option<SourceLocation>,
1453 /// The enclosure type/label
1454 pub label: String,
1455 /// Optional background color
1456 pub background_color: Option<String>,
1457 /// Optional border color
1458 pub border_color: Option<String>,
1459 /// The enclosed expression
1460 pub body: Box<AnyParseNode>,
1461}
1462
1463/// Represents custom mathematical environments.
1464///
1465/// This struct handles user-defined or custom mathematical environments
1466/// that extend beyond the standard KaTeX environments.
1467///
1468/// # Fields
1469///
1470/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1471/// * `loc` - Optional source location for error reporting
1472/// * `name` - The environment name
1473/// * `name_group` - The parsed name as an expression
1474///
1475///
1476/// # Usage
1477///
1478/// Environment nodes support custom mathematical constructs and
1479/// user-defined environments in LaTeX documents.
1480#[derive(Debug, Clone, PartialEq)]
1481pub struct ParseNodeEnvironment {
1482 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1483 pub mode: Mode,
1484 /// Optional source location for error reporting
1485 pub loc: Option<SourceLocation>,
1486 /// The environment name
1487 pub name: String,
1488 /// The parsed name as an expression
1489 pub name_group: Box<AnyParseNode>,
1490}
1491
1492impl From<ParseNodeEnvironment> for AnyParseNode {
1493 fn from(value: ParseNodeEnvironment) -> Self {
1494 Self::Environment(Box::new(value))
1495 }
1496}
1497
1498/// Represents font changes applied to mathematical expressions.
1499///
1500/// This struct handles font family changes for mathematical content,
1501/// allowing different typefaces within expressions.
1502///
1503/// # Fields
1504///
1505/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1506/// * `loc` - Optional source location for error reporting
1507/// * `font` - The font family name
1508/// * `body` - The expression in the specified font
1509///
1510/// # LaTeX Correspondence
1511///
1512/// Corresponds to LaTeX font commands:
1513/// ```latex
1514/// \mathrm{dx} % Roman/upright
1515/// \mathbf{v} % Bold
1516/// \mathit{f} % Italic
1517/// \mathsf{S} % Sans-serif
1518/// ```
1519///
1520/// # Usage
1521///
1522/// Font nodes control the typeface of mathematical symbols, essential for
1523/// distinguishing different types of mathematical objects (scalars, vectors,
1524/// etc.).
1525#[derive(Debug, Clone, PartialEq)]
1526pub struct ParseNodeFont {
1527 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1528 pub mode: Mode,
1529 /// Optional source location for error reporting
1530 pub loc: Option<SourceLocation>,
1531 /// The font family name
1532 pub font: String,
1533 /// The expression in the specified font
1534 pub body: Box<AnyParseNode>,
1535}
1536
1537/// Represents generalized fractions and binomial coefficients.
1538///
1539/// This struct handles various types of fractions including regular fractions,
1540/// binomial coefficients, and other stacked expressions with optional
1541/// delimiters.
1542///
1543/// # Fields
1544///
1545/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1546/// * `loc` - Optional source location for error reporting
1547/// * `continued` - Whether this is a continued fraction
1548/// * `numer` - The numerator expression
1549/// * `denom` - The denominator expression
1550/// * `has_bar_line` - Whether to draw a fraction bar
1551/// * `left_delim` - Optional left delimiter
1552/// * `right_delim` - Optional right delimiter
1553/// * `size` - The display size ([`Style`])
1554/// * `bar_size` - Optional custom bar thickness
1555///
1556/// # LaTeX Correspondence
1557///
1558/// Corresponds to LaTeX fraction commands:
1559/// ```latex
1560/// \frac{1}{2} % Regular fraction
1561/// \binom{n}{k} % Binomial coefficient
1562/// \dfrac{a}{b} % Display style fraction
1563/// \cfrac{1}{1+x} % Continued fraction
1564/// ```
1565///
1566/// # Usage
1567///
1568/// Genfrac nodes are fundamental for representing ratios, probabilities,
1569/// and complex mathematical relationships in stacked form.
1570#[derive(Debug, Clone, PartialEq)]
1571pub struct ParseNodeGenfrac {
1572 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1573 pub mode: Mode,
1574 /// Optional source location for error reporting
1575 pub loc: Option<SourceLocation>,
1576 /// Whether this is a continued fraction
1577 pub continued: bool,
1578 /// The numerator expression
1579 pub numer: Box<AnyParseNode>,
1580 /// The denominator expression
1581 pub denom: Box<AnyParseNode>,
1582 /// Whether to draw a fraction bar
1583 pub has_bar_line: bool,
1584 /// Optional left delimiter
1585 pub left_delim: Option<String>,
1586 /// Optional right delimiter
1587 pub right_delim: Option<String>,
1588 /// The display size ([`Style`])
1589 /// Corresponds to KaTeX's `\genfrac` size parameter:
1590 /// If this is None, the equivalent to "auto" is used.
1591 pub size: Option<&'static Style>,
1592 /// Optional custom bar thickness
1593 pub bar_size: Option<MeasurementOwned>,
1594}
1595
1596/// Represents horizontal boxes for grouping mathematical content.
1597///
1598/// This struct handles horizontal grouping of mathematical expressions
1599/// that should be treated as a single unit for layout purposes.
1600///
1601/// # Fields
1602///
1603/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1604/// * `loc` - Optional source location for error reporting
1605/// * `body` - The expressions contained in the horizontal box
1606///
1607/// # LaTeX Correspondence
1608///
1609/// Corresponds to LaTeX horizontal box commands:
1610/// ```latex
1611/// \hbox{ab} % Horizontal box
1612/// \mbox{xy} % Math box
1613/// ```
1614///
1615/// # Usage
1616///
1617/// Hbox nodes control horizontal spacing and grouping of mathematical elements,
1618/// ensuring they are treated as a single layout unit.
1619#[derive(Debug, Clone, PartialEq)]
1620pub struct ParseNodeHbox {
1621 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1622 pub mode: Mode,
1623 /// Optional source location for error reporting
1624 pub loc: Option<SourceLocation>,
1625 /// The expressions contained in the horizontal box
1626 pub body: Vec<AnyParseNode>,
1627}
1628
1629/// Represents horizontal braces above or below mathematical expressions.
1630///
1631/// This struct handles overbraces and underbraces that span multiple symbols
1632/// with optional labels for annotation.
1633///
1634/// # Fields
1635///
1636/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1637/// * `loc` - Optional source location for error reporting
1638/// * `label` - The brace label/annotation
1639/// * `is_over` - Whether the brace is above (true) or below (false)
1640/// * `base` - The expression being braced
1641///
1642///
1643/// # LaTeX Correspondence
1644///
1645/// Corresponds to LaTeX brace commands:
1646/// ```latex
1647/// \overbrace{abc}^{sum} % Overbrace
1648/// \underbrace{xyz}_{total} % Underbrace
1649/// ```
1650///
1651/// # Usage
1652///
1653/// HorizBrace nodes provide visual grouping and annotation of related
1654/// mathematical terms or operations.
1655#[derive(Debug, Clone, PartialEq)]
1656pub struct ParseNodeHorizBrace {
1657 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1658 pub mode: Mode,
1659 /// Optional source location for error reporting
1660 pub loc: Option<SourceLocation>,
1661 /// The brace label/annotation
1662 pub label: String,
1663 /// Whether the brace is above (true) or below (false)
1664 pub is_over: bool,
1665 /// The expression being braced
1666 pub base: Box<AnyParseNode>,
1667}
1668
1669/// Represents hyperlink references within mathematical expressions.
1670///
1671/// This struct handles clickable links in mathematical content,
1672/// allowing expressions to link to external resources or references.
1673///
1674/// # Fields
1675///
1676/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1677/// * `loc` - Optional source location for error reporting
1678/// * `href` - The hyperlink URL
1679/// * `body` - The linked mathematical expression
1680///
1681///
1682/// # LaTeX Correspondence
1683///
1684/// Corresponds to LaTeX hyperlink commands:
1685/// ```latex
1686/// \href{https://example.com}{x}
1687/// \url{https://example.com}
1688/// ```
1689///
1690/// # Usage
1691///
1692/// Href nodes enable interactive mathematical documents with embedded
1693/// navigation and reference links.
1694#[derive(Debug, Clone, PartialEq)]
1695pub struct ParseNodeHref {
1696 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1697 pub mode: Mode,
1698 /// Optional source location for error reporting
1699 pub loc: Option<SourceLocation>,
1700 /// The hyperlink URL
1701 pub href: String,
1702 /// The linked mathematical expression
1703 pub body: Vec<AnyParseNode>,
1704}
1705
1706/// Represents embedded HTML content within mathematical expressions.
1707///
1708/// This struct handles raw HTML that needs to be included in the
1709/// rendered mathematical output.
1710///
1711/// # Fields
1712///
1713/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1714/// * `loc` - Optional source location for error reporting
1715/// * `attributes` - HTML attributes as key-value pairs
1716/// * `body` - The HTML content as parse nodes
1717///
1718/// # Usage
1719///
1720/// HTML nodes allow embedding custom HTML elements within mathematical
1721/// expressions for advanced formatting or interactivity.
1722#[derive(Debug, Clone, PartialEq)]
1723pub struct ParseNodeHtml {
1724 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1725 pub mode: Mode,
1726 /// Optional source location for error reporting
1727 pub loc: Option<SourceLocation>,
1728 /// HTML attributes as key-value pairs
1729 pub attributes: KeyMap<String, String>,
1730 /// The HTML content as parse nodes
1731 pub body: Vec<AnyParseNode>,
1732}
1733
1734/// Represents content that can be rendered in both HTML and MathML formats.
1735///
1736/// This struct handles mathematical expressions that have different
1737/// representations for HTML and MathML output formats.
1738///
1739/// # Fields
1740///
1741/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1742/// * `loc` - Optional source location for error reporting
1743/// * `html` - HTML representation
1744/// * `mathml` - MathML representation
1745///
1746/// # Usage
1747///
1748/// HtmlMathMl nodes support dual-format output for better compatibility
1749/// across different rendering engines and accessibility tools.
1750#[derive(Debug, Clone, PartialEq)]
1751pub struct ParseNodeHtmlMathMl {
1752 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1753 pub mode: Mode,
1754 /// Optional source location for error reporting
1755 pub loc: Option<SourceLocation>,
1756 /// HTML representation
1757 pub html: Vec<AnyParseNode>,
1758 /// MathML representation
1759 pub mathml: Vec<AnyParseNode>,
1760}
1761
1762/// Represents included graphics/images within mathematical expressions.
1763///
1764/// This struct handles the inclusion of external images or graphics
1765/// that are part of mathematical content.
1766///
1767/// # Fields
1768///
1769/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1770/// * `loc` - Optional source location for error reporting
1771/// * `alt` - Alternative text for accessibility
1772/// * `width` - Image width ([`MeasurementOwned`])
1773/// * `height` - Image height ([`MeasurementOwned`])
1774/// * `total_height` - Total height including depth
1775/// * `src` - Image source path/URL
1776///
1777/// # LaTeX Correspondence
1778///
1779/// Corresponds to LaTeX include graphics commands:
1780/// ```latex
1781/// \includegraphics[width=5em]{diagram.png}
1782/// \includegraphics[height=3em]{figure.jpg}
1783/// ```
1784///
1785/// # Usage
1786///
1787/// Includegraphics nodes allow embedding diagrams, plots, and other
1788/// visual elements within mathematical expressions.
1789#[derive(Debug, Clone, PartialEq)]
1790pub struct ParseNodeIncludegraphics {
1791 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1792 pub mode: Mode,
1793 /// Optional source location for error reporting
1794 pub loc: Option<SourceLocation>,
1795 /// Alternative text for accessibility
1796 pub alt: String,
1797 /// Image width ([`MeasurementOwned`])
1798 pub width: MeasurementOwned,
1799 /// Image height ([`MeasurementOwned`])
1800 pub height: MeasurementOwned,
1801 /// Total height including depth
1802 pub total_height: MeasurementOwned,
1803 /// Image source path/URL
1804 pub src: String,
1805}
1806
1807/// Represents infix operators in mathematical expressions.
1808///
1809/// This struct handles operators that appear between operands,
1810/// such as custom or extensible operators.
1811///
1812/// # Fields
1813///
1814/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1815/// * `loc` - Optional source location for error reporting
1816/// * `replace_with` - The replacement string for the operator
1817/// * `size` - Optional size specification
1818/// * `token` - Optional associated token
1819///
1820/// # Usage
1821///
1822/// Infix nodes handle custom operators and extensible operator syntax
1823/// in mathematical expressions.
1824#[derive(Debug, Clone, PartialEq)]
1825pub struct ParseNodeInfix {
1826 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1827 pub mode: Mode,
1828 /// Optional source location for error reporting
1829 pub loc: Option<SourceLocation>,
1830 /// The replacement string for the operator
1831 pub replace_with: String,
1832 /// Optional size specification
1833 pub size: Option<MeasurementOwned>,
1834 /// Optional associated token
1835 pub token: Option<Token>,
1836}
1837
1838/// Represents internal parser nodes for implementation details.
1839///
1840/// This struct handles nodes used internally by the parser for
1841/// processing and transformation purposes.
1842///
1843/// # Fields
1844///
1845/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1846/// * `loc` - Optional source location for error reporting
1847///
1848/// # Usage
1849///
1850/// Internal nodes are used for parser implementation details and
1851/// intermediate processing steps.
1852#[derive(Debug, Clone, PartialEq, Eq)]
1853pub struct ParseNodeInternal {
1854 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1855 pub mode: Mode,
1856 /// Optional source location for error reporting
1857 pub loc: Option<SourceLocation>,
1858}
1859
1860/// Represents explicit kerning/spacing adjustments in mathematical expressions.
1861///
1862/// This struct handles manual spacing adjustments between mathematical elements
1863/// for precise layout control.
1864///
1865/// # Fields
1866///
1867/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1868/// * `loc` - Optional source location for error reporting
1869/// * `dimension` - The spacing amount ([`MeasurementOwned`])
1870///
1871/// # LaTeX Correspondence
1872///
1873/// Corresponds to LaTeX kerning commands:
1874/// ```latex
1875/// \kern 0.5em % Positive kerning
1876/// \mkern 3mu % Math unit kerning
1877/// ```
1878///
1879/// # Usage
1880///
1881/// Kern nodes provide fine-grained control over spacing in mathematical
1882/// expressions for typographical precision.
1883#[derive(Debug, Clone, PartialEq)]
1884pub struct ParseNodeKern {
1885 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1886 pub mode: Mode,
1887 /// Optional source location for error reporting
1888 pub loc: Option<SourceLocation>,
1889 /// The spacing amount ([`MeasurementOwned`])
1890 pub dimension: MeasurementOwned,
1891}
1892
1893/// Represents overlapping content (lap) in mathematical expressions.
1894///
1895/// This struct handles text or symbols that overlap other content,
1896/// commonly used for annotations or special positioning.
1897///
1898/// # Fields
1899///
1900/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1901/// * `loc` - Optional source location for error reporting
1902/// * `alignment` - The alignment for overlapping ("l", "r", "c")
1903/// * `body` - The overlapping content
1904///
1905/// # LaTeX Correspondence
1906///
1907/// Corresponds to LaTeX lap commands:
1908/// ```latex
1909/// \rlap{*} % Right overlap
1910/// \llap{#} % Left overlap
1911/// \clap{^} % Center overlap
1912/// ```
1913///
1914/// # Usage
1915///
1916/// Lap nodes enable overlapping text for annotations, superscripts,
1917/// or special positioning requirements.
1918#[derive(Debug, Clone, PartialEq)]
1919pub struct ParseNodeLap {
1920 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1921 pub mode: Mode,
1922 /// Optional source location for error reporting
1923 pub loc: Option<SourceLocation>,
1924 /// The alignment for overlapping ("l", "r", "c")
1925 pub alignment: LapAlignment,
1926 /// The overlapping content
1927 pub body: Box<AnyParseNode>,
1928}
1929
1930/// Alignment options for overlapping content.
1931#[derive(Debug, Clone, PartialEq, Eq)]
1932pub enum LapAlignment {
1933 /// Align left
1934 Left,
1935 /// Align center
1936 Center,
1937 /// Align right
1938 Right,
1939}
1940
1941impl LapAlignment {
1942 /// Get as static string reference.
1943 #[must_use]
1944 pub const fn as_str(&self) -> &'static str {
1945 match self {
1946 Self::Left => "llap",
1947 Self::Center => "clap",
1948 Self::Right => "rlap",
1949 }
1950 }
1951}
1952
1953/// Represents left-right delimiter pairs in mathematical expressions.
1954///
1955/// This struct handles matching delimiter pairs that enclose mathematical
1956/// content, such as parentheses, brackets, and braces with automatic sizing.
1957///
1958/// # Fields
1959///
1960/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1961/// * `loc` - Optional source location for error reporting
1962/// * `body` - The enclosed mathematical expressions
1963/// * `left` - The left delimiter symbol
1964/// * `right` - The right delimiter symbol
1965/// * `right_color` - Optional color for the right delimiter
1966///
1967///
1968/// # LaTeX Correspondence
1969///
1970/// Corresponds to LaTeX left-right delimiters:
1971/// ```latex
1972/// \left( \frac{a}{b} \right)
1973/// \left[ x + y \right]
1974/// \left\{ a, b, c \right\}
1975/// ```
1976///
1977/// # Usage
1978///
1979/// LeftRight nodes automatically size delimiters to fit their content,
1980/// ensuring proper visual grouping of mathematical expressions.
1981#[derive(Debug, Clone, PartialEq)]
1982pub struct ParseNodeLeftRight {
1983 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
1984 pub mode: Mode,
1985 /// Optional source location for error reporting
1986 pub loc: Option<SourceLocation>,
1987 /// The enclosed mathematical expressions
1988 pub body: Vec<AnyParseNode>,
1989 /// The left delimiter symbol
1990 pub left: String,
1991 /// The right delimiter symbol
1992 pub right: String,
1993 /// Optional color for the right delimiter
1994 pub right_color: Option<String>,
1995}
1996
1997/// Represents right delimiters in left-right pairs.
1998///
1999/// This struct handles the right delimiter in a left-right delimiter pair,
2000/// allowing for separate styling or coloring.
2001///
2002/// # Fields
2003///
2004/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2005/// * `loc` - Optional source location for error reporting
2006/// * `delim` - The delimiter symbol
2007/// * `color` - Optional color specification
2008///
2009/// # Usage
2010///
2011/// LeftRightRight nodes handle the right side of delimiter pairs,
2012/// supporting different styling from the left delimiter.
2013#[derive(Debug, Clone, PartialEq, Eq)]
2014pub struct ParseNodeLeftRightRight {
2015 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2016 pub mode: Mode,
2017 /// Optional source location for error reporting
2018 pub loc: Option<SourceLocation>,
2019 /// The delimiter symbol
2020 pub delim: String,
2021 /// Optional color specification
2022 pub color: Option<String>,
2023}
2024
2025/// Represents different renderings for various math styles.
2026///
2027/// This struct handles expressions that display differently depending on the
2028/// mathematical context (display, text, script, scriptscript sizes).
2029///
2030/// # Fields
2031///
2032/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2033/// * `loc` - Optional source location for error reporting
2034/// * `display` - Display style rendering
2035/// * `text` - Text style rendering
2036/// * `script` - Script style rendering
2037/// * `scriptscript` - Scriptscript style rendering
2038///
2039/// # LaTeX Correspondence
2040///
2041/// Corresponds to LaTeX math choice command:
2042/// ```latex
2043/// \mathchoice{\sum}{\sum}{\sum}{\sum}
2044/// ```
2045///
2046/// # Usage
2047///
2048/// MathChoice nodes allow different visual representations based on the
2049/// mathematical context, ensuring optimal readability at different sizes.
2050#[derive(Debug, Clone, PartialEq)]
2051pub struct ParseNodeMathChoice {
2052 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2053 pub mode: Mode,
2054 /// Optional source location for error reporting
2055 pub loc: Option<SourceLocation>,
2056 /// Display style rendering
2057 pub display: Vec<AnyParseNode>,
2058 /// Text style rendering
2059 pub text: Vec<AnyParseNode>,
2060 /// Script style rendering
2061 pub script: Vec<AnyParseNode>,
2062 /// Scriptscript style rendering
2063 pub scriptscript: Vec<AnyParseNode>,
2064}
2065
2066/// Represents middle delimiters in mathematical expressions.
2067///
2068/// This struct handles delimiters that appear in the middle of expressions,
2069/// such as separators in continued fractions or special punctuation.
2070///
2071/// # Fields
2072///
2073/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2074/// * `loc` - Optional source location for error reporting
2075/// * `delim` - The delimiter symbol
2076///
2077///
2078/// # LaTeX Correspondence
2079///
2080/// Corresponds to LaTeX middle delimiters:
2081/// ```latex
2082/// \middle|
2083/// \middle.
2084/// ```
2085///
2086/// # Usage
2087///
2088/// Middle nodes handle delimiters that separate parts of mathematical
2089/// expressions without being part of left-right pairs.
2090#[derive(Debug, Clone, PartialEq, Eq)]
2091pub struct ParseNodeMiddle {
2092 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2093 pub mode: Mode,
2094 /// Optional source location for error reporting
2095 pub loc: Option<SourceLocation>,
2096 /// The delimiter symbol
2097 pub delim: String,
2098}
2099
2100/// Represents math class specifications for mathematical elements.
2101///
2102/// This struct handles the classification of mathematical symbols for
2103/// proper spacing and rendering behavior.
2104///
2105/// # Fields
2106///
2107/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2108/// * `loc` - Optional source location for error reporting
2109/// * `mclass` - The math class ("mord", "mbin", "mrel", etc.)
2110/// * `body` - The mathematical expressions
2111/// * `is_character_box` - Whether this represents a single character box
2112///
2113///
2114/// # Usage
2115///
2116/// Mclass nodes control the spacing and positioning behavior of mathematical
2117/// elements according to their semantic classification.
2118#[derive(Debug, Clone, PartialEq)]
2119pub struct ParseNodeMclass {
2120 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2121 pub mode: Mode,
2122 /// Optional source location for error reporting
2123 pub loc: Option<SourceLocation>,
2124 /// The math class ("mord", "mbin", "mrel", etc.)
2125 pub mclass: DomType,
2126 /// The mathematical expressions
2127 pub body: Vec<AnyParseNode>,
2128 /// Whether this represents a single character box
2129 pub is_character_box: bool,
2130}
2131
2132/// Represents operator names with special formatting.
2133///
2134/// This struct handles named operators like "lim", "max", "sin" that
2135/// have specific formatting rules for subscripts and superscripts.
2136///
2137/// # Fields
2138///
2139/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2140/// * `loc` - Optional source location for error reporting
2141/// * `body` - The operator name content
2142/// * `always_handle_sup_sub` - Force special subscript/superscript handling
2143/// * `limits` - Whether to place limits above/below (true) or as scripts
2144/// (false)
2145/// * `parent_is_sup_sub` - Whether this is within a sup/sub context
2146///
2147///
2148/// # LaTeX Correspondence
2149///
2150/// Corresponds to LaTeX operator name commands:
2151/// ```latex
2152/// \lim_{x \to 0} f(x)
2153/// \max_{a,b} f(a,b)
2154/// \sin^2 \theta
2155/// ```
2156///
2157/// # Usage
2158///
2159/// OperatorName nodes ensure proper formatting of mathematical operators
2160/// with their arguments and limits.
2161#[derive(Debug, Clone, PartialEq)]
2162pub struct ParseNodeOperatorName {
2163 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2164 pub mode: Mode,
2165 /// Optional source location for error reporting
2166 pub loc: Option<SourceLocation>,
2167 /// The operator name content
2168 pub body: Vec<AnyParseNode>,
2169 /// Force special subscript/superscript handling
2170 pub always_handle_sup_sub: bool,
2171 /// Whether to place limits above/below (true) or as scripts (false)
2172 pub limits: bool,
2173 /// Whether this is within a sup/sub context
2174 pub parent_is_sup_sub: bool,
2175}
2176
2177/// Represents overlines above mathematical expressions.
2178///
2179/// This struct handles horizontal lines drawn above mathematical content
2180/// for emphasis or special notation.
2181///
2182/// # Fields
2183///
2184/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2185/// * `loc` - Optional source location for error reporting
2186/// * `body` - The expression being overlined
2187///
2188/// # LaTeX Correspondence
2189///
2190/// Corresponds to LaTeX overline command:
2191/// ```latex
2192/// \overline{ABC}
2193/// ```
2194///
2195/// # Usage
2196///
2197/// Overline nodes provide visual emphasis for mathematical expressions,
2198/// commonly used for repeating decimals or special notation.
2199#[derive(Debug, Clone, PartialEq)]
2200pub struct ParseNodeOverline {
2201 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2202 pub mode: Mode,
2203 /// Optional source location for error reporting
2204 pub loc: Option<SourceLocation>,
2205 /// The expression being overlined
2206 pub body: Box<AnyParseNode>,
2207}
2208
2209/// Represents phantom content for spacing purposes.
2210///
2211/// This struct handles invisible content that affects layout and spacing
2212/// without being visible in the final output.
2213///
2214/// # Fields
2215///
2216/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2217/// * `loc` - Optional source location for error reporting
2218/// * `body` - The phantom content (invisible but affects spacing)
2219///
2220/// # LaTeX Correspondence
2221///
2222/// Corresponds to LaTeX phantom commands:
2223/// ```latex
2224/// \phantom{x} % Invisible but takes space
2225/// \hphantom{y} % Horizontal space only
2226/// \vphantom{z} % Vertical space only
2227/// ```
2228///
2229/// # Usage
2230///
2231/// Phantom nodes allow precise control over spacing and alignment by
2232/// including invisible content that affects layout calculations.
2233#[derive(Debug, Clone, PartialEq)]
2234pub struct ParseNodePhantom {
2235 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2236 pub mode: Mode,
2237 /// Optional source location for error reporting
2238 pub loc: Option<SourceLocation>,
2239 /// The phantom content (invisible but affects spacing)
2240 pub body: Vec<AnyParseNode>,
2241}
2242
2243/// Represents horizontal phantom content.
2244///
2245/// This struct handles invisible content that only affects horizontal spacing
2246/// and width calculations.
2247///
2248/// # Fields
2249///
2250/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2251/// * `loc` - Optional source location for error reporting
2252/// * `body` - The horizontal phantom content
2253///
2254/// # Usage
2255///
2256/// Hphantom nodes reserve horizontal space without vertical extent,
2257/// useful for alignment and spacing control.
2258#[derive(Debug, Clone, PartialEq)]
2259pub struct ParseNodeHphantom {
2260 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2261 pub mode: Mode,
2262 /// Optional source location for error reporting
2263 pub loc: Option<SourceLocation>,
2264 /// The horizontal phantom content
2265 pub body: Box<AnyParseNode>,
2266}
2267
2268/// Represents vertical phantom content.
2269///
2270/// This struct handles invisible content that only affects vertical spacing
2271/// and height calculations.
2272///
2273/// # Fields
2274///
2275/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2276/// * `loc` - Optional source location for error reporting
2277/// * `body` - The vertical phantom content
2278///
2279///
2280/// # Usage
2281///
2282/// Vphantom nodes reserve vertical space without horizontal extent,
2283/// useful for consistent baseline alignment.
2284#[derive(Debug, Clone, PartialEq)]
2285pub struct ParseNodeVphantom {
2286 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2287 pub mode: Mode,
2288 /// Optional source location for error reporting
2289 pub loc: Option<SourceLocation>,
2290 /// The vertical phantom content
2291 pub body: Box<AnyParseNode>,
2292}
2293
2294/// Represents poor man's bold text formatting.
2295///
2296/// This struct handles bold formatting created by overprinting characters,
2297/// used when proper bold fonts are not available.
2298///
2299/// # Fields
2300///
2301/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2302/// * `loc` - Optional source location for error reporting
2303/// * `mclass` - The math class of the content
2304/// * `body` - The content to be made bold
2305///
2306///
2307/// # LaTeX Correspondence
2308///
2309/// Corresponds to LaTeX poor man's bold:
2310/// ```latex
2311/// \pmb{x} % Poor man's bold
2312/// ```
2313///
2314/// # Usage
2315///
2316/// Pmb nodes create bold appearance by slight overprinting of characters,
2317/// useful for mathematical notation when bold fonts are unavailable.
2318#[derive(Debug, Clone, PartialEq)]
2319pub struct ParseNodePmb {
2320 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2321 pub mode: Mode,
2322 /// Optional source location for error reporting
2323 pub loc: Option<SourceLocation>,
2324 /// The math class of the content
2325 pub mclass: DomType,
2326 /// The content to be made bold
2327 pub body: Vec<AnyParseNode>,
2328}
2329
2330/// Represents raised or lowered content in mathematical expressions.
2331///
2332/// This struct handles vertical displacement of mathematical content
2333/// for special positioning requirements.
2334///
2335/// # Fields
2336///
2337/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2338/// * `loc` - Optional source location for error reporting
2339/// * `dy` - The vertical displacement amount ([`MeasurementOwned`])
2340/// * `body` - The content to be displaced
2341///
2342/// # LaTeX Correspondence
2343///
2344/// Corresponds to LaTeX raisebox command:
2345/// ```latex
2346/// \raisebox{0.5em}{x}
2347/// ```
2348///
2349/// # Usage
2350///
2351/// Raisebox nodes allow precise vertical positioning of mathematical elements
2352/// for special layout requirements.
2353#[derive(Debug, Clone, PartialEq)]
2354pub struct ParseNodeRaisebox {
2355 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2356 pub mode: Mode,
2357 /// Optional source location for error reporting
2358 pub loc: Option<SourceLocation>,
2359 /// The vertical displacement amount ([`MeasurementOwned`])
2360 pub dy: MeasurementOwned,
2361 /// The content to be displaced
2362 pub body: Box<AnyParseNode>,
2363}
2364
2365/// Represents horizontal or vertical rules in mathematical expressions.
2366///
2367/// This struct handles the creation of straight lines for various
2368/// mathematical notation purposes.
2369///
2370/// # Fields
2371///
2372/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2373/// * `loc` - Optional source location for error reporting
2374/// * `shift` - Optional vertical shift of the rule
2375/// * `width` - The width of the rule ([`MeasurementOwned`])
2376/// * `height` - The height/thickness of the rule ([`MeasurementOwned`])
2377///
2378/// # LaTeX Correspondence
2379///
2380/// Corresponds to LaTeX rule command:
2381/// ```latex
2382/// \rule{2em}{0.1em}
2383/// ```
2384///
2385/// # Usage
2386///
2387/// Rule nodes create horizontal or vertical lines for mathematical
2388/// notation, such as fraction bars or special symbols.
2389#[derive(Debug, Clone, PartialEq)]
2390pub struct ParseNodeRule {
2391 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2392 pub mode: Mode,
2393 /// Optional source location for error reporting
2394 pub loc: Option<SourceLocation>,
2395 /// Optional vertical shift of the rule
2396 pub shift: Option<MeasurementOwned>,
2397 /// The width of the rule ([`MeasurementOwned`])
2398 pub width: MeasurementOwned,
2399 /// The height/thickness of the rule ([`MeasurementOwned`])
2400 pub height: MeasurementOwned,
2401}
2402
2403/// Represents size changes for mathematical expressions.
2404///
2405/// This struct handles scaling of mathematical content to different
2406/// display sizes for various contexts.
2407///
2408/// # Fields
2409///
2410/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2411/// * `loc` - Optional source location for error reporting
2412/// * `size` - The size level/index
2413/// * `body` - The expressions to be sized
2414///
2415///
2416/// # LaTeX Correspondence
2417///
2418/// Corresponds to LaTeX sizing commands:
2419/// ```latex
2420/// \scriptsize x
2421/// \large y
2422/// \Huge z
2423/// ```
2424///
2425/// # Usage
2426///
2427/// Sizing nodes control the scale of mathematical expressions for
2428/// different display contexts and emphasis.
2429#[derive(Debug, Clone, PartialEq)]
2430pub struct ParseNodeSizing {
2431 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2432 pub mode: Mode,
2433 /// Optional source location for error reporting
2434 pub loc: Option<SourceLocation>,
2435 /// The size level/index
2436 pub size: usize,
2437 /// The expressions to be sized
2438 pub body: Vec<AnyParseNode>,
2439}
2440
2441/// Represents smashed content that ignores height or depth.
2442///
2443/// This struct handles content where the height or depth is ignored
2444/// for layout purposes, useful for alignment control.
2445///
2446/// # Fields
2447///
2448/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2449/// * `loc` - Optional source location for error reporting
2450/// * `body` - The content to be smashed
2451/// * `smash_height` - Whether to ignore the height above baseline
2452/// * `smash_depth` - Whether to ignore the depth below baseline
2453///
2454/// # LaTeX Correspondence
2455///
2456/// Corresponds to LaTeX smash commands:
2457/// ```latex
2458/// \smash{x} % Smash both
2459/// \smash[t]{y} % Smash top only
2460/// \smash[b]{z} % Smash bottom only
2461/// ```
2462///
2463/// # Usage
2464///
2465/// Smash nodes allow content to be treated as having zero height or depth
2466/// for alignment purposes without affecting the actual rendering.
2467#[derive(Debug, Clone, PartialEq)]
2468pub struct ParseNodeSmash {
2469 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2470 pub mode: Mode,
2471 /// Optional source location for error reporting
2472 pub loc: Option<SourceLocation>,
2473 /// The content to be smashed
2474 pub body: Box<AnyParseNode>,
2475 /// Whether to ignore the height above baseline
2476 pub smash_height: bool,
2477 /// Whether to ignore the depth below baseline
2478 pub smash_depth: bool,
2479}
2480
2481/// Represents square roots and nth roots in mathematical expressions.
2482///
2483/// This struct handles radical expressions with optional indices
2484/// for nth roots.
2485///
2486/// # Fields
2487///
2488/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2489/// * `loc` - Optional source location for error reporting
2490/// * `body` - The expression under the radical
2491/// * `index` - Optional index for nth roots
2492///
2493/// # LaTeX Correspondence
2494///
2495/// Corresponds to LaTeX radical commands:
2496/// ```latex
2497/// \sqrt{x} % Square root
2498/// \sqrt[3]{x} % Cube root
2499/// \sqrt[n]{x} % nth root
2500/// ```
2501///
2502/// # Usage
2503///
2504/// Sqrt nodes represent radical expressions, automatically sizing the
2505/// radical symbol to fit the content and handling nth root indices.
2506#[derive(Debug, Clone, PartialEq)]
2507pub struct ParseNodeSqrt {
2508 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2509 pub mode: Mode,
2510 /// Optional source location for error reporting
2511 pub loc: Option<SourceLocation>,
2512 /// The expression under the radical
2513 pub body: AnyParseNode,
2514 /// Optional index for nth roots
2515 pub index: Option<AnyParseNode>,
2516}
2517
2518/// Represents underlines below mathematical expressions.
2519///
2520/// This struct handles horizontal lines drawn below mathematical content
2521/// for emphasis or special notation.
2522///
2523/// # Fields
2524///
2525/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2526/// * `loc` - Optional source location for error reporting
2527/// * `body` - The expression being underlined
2528///
2529/// # LaTeX Correspondence
2530///
2531/// Corresponds to LaTeX underline command:
2532/// ```latex
2533/// \underline{ABC}
2534/// ```
2535///
2536/// # Usage
2537///
2538/// Underline nodes provide visual emphasis for mathematical expressions,
2539/// commonly used for highlighting or special notation.
2540#[derive(Debug, Clone, PartialEq)]
2541pub struct ParseNodeUnderline {
2542 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2543 pub mode: Mode,
2544 /// Optional source location for error reporting
2545 pub loc: Option<SourceLocation>,
2546 /// The expression being underlined
2547 pub body: Box<AnyParseNode>,
2548}
2549
2550/// Represents vertically centered content in mathematical expressions.
2551///
2552/// This struct handles content that should be centered vertically
2553/// relative to the current line.
2554///
2555/// # Fields
2556///
2557/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2558/// * `loc` - Optional source location for error reporting
2559/// * `body` - The content to be vertically centered
2560///
2561/// # LaTeX Correspondence
2562///
2563/// Corresponds to LaTeX vcenter command:
2564/// ```latex
2565/// \vcenter{x}
2566/// ```
2567///
2568/// # Usage
2569///
2570/// Vcenter nodes center content vertically, useful for aligning
2571/// elements in complex mathematical layouts.
2572#[derive(Debug, Clone, PartialEq)]
2573pub struct ParseNodeVcenter {
2574 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2575 pub mode: Mode,
2576 /// Optional source location for error reporting
2577 pub loc: Option<SourceLocation>,
2578 /// The content to be vertically centered
2579 pub body: Box<AnyParseNode>,
2580}
2581
2582/// Represents extensible arrows in mathematical expressions.
2583///
2584/// This struct handles arrows that can stretch to fit their content,
2585/// with optional labels above or below.
2586///
2587/// # Fields
2588///
2589/// * `mode` - The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2590/// * `loc` - Optional source location for error reporting
2591/// * `label` - The arrow type/label (e.g., "->", "<=>")
2592/// * `body` - The content above the arrow
2593/// * `below` - Optional content below the arrow
2594///
2595/// # LaTeX Correspondence
2596///
2597/// Corresponds to LaTeX extensible arrow commands:
2598/// ```latex
2599/// \xleftarrow{f}
2600/// \xrightarrow[g]{f}
2601/// \xleftrightarrow{h}
2602/// ```
2603///
2604/// # Usage
2605///
2606/// XArrow nodes create arrows that automatically size to fit their labels,
2607/// commonly used for function mappings and transformations.
2608#[derive(Debug, Clone, PartialEq)]
2609pub struct ParseNodeXArrow {
2610 /// The parsing mode ([`Mode::Math`] or [`Mode::Text`])
2611 pub mode: Mode,
2612 /// Optional source location for error reporting
2613 pub loc: Option<SourceLocation>,
2614 /// The arrow type/label (e.g., "->", "<=>")
2615 pub label: String,
2616 /// The content above the arrow
2617 pub body: Option<Box<AnyParseNode>>,
2618 /// Optional content below the arrow
2619 pub below: Option<Box<AnyParseNode>>,
2620}
2621
2622/// Type alias for symbol parse nodes that represent individual mathematical
2623/// symbols.
2624///
2625/// This alias refers to the subset of [`AnyParseNode`] variants that represent
2626/// atomic mathematical symbols with specific spacing and rendering properties.
2627/// These include atoms, operators, ordinals, and other symbol-like elements.
2628///
2629/// # Symbol Types
2630///
2631/// The following [`AnyParseNode`] variants are considered symbol nodes:
2632/// * [`AnyParseNode::Atom`] - Atomic symbols with mathematical meaning
2633/// * [`AnyParseNode::MathOrd`] - Ordinary mathematical symbols
2634/// * [`AnyParseNode::Op`] - Mathematical operators
2635/// * [`AnyParseNode::Spacing`] - Explicit spacing elements
2636/// * [`AnyParseNode::TextOrd`] - Text symbols in math mode
2637/// * [`AnyParseNode::AccentToken`] - Accent symbol components
2638/// * [`AnyParseNode::OpToken`] - Operator symbol components
2639///
2640/// # Usage
2641///
2642/// Used for type checking and validation when a function expects only
2643/// symbol-type nodes. The utility functions [`check_symbol_node_type`] and
2644/// [`assert_symbol_node_type`] work specifically with this type of node.
2645///
2646/// # See Also
2647///
2648/// * [`check_symbol_node_type`] - Check if a node is a symbol node
2649/// * [`assert_symbol_node_type`] - Assert that a node is a symbol node
2650pub type SymbolParseNode = AnyParseNode;
2651
2652/// Type alias for parse nodes representing unsupported or partially supported
2653/// commands.
2654///
2655/// This alias currently refers to color-related nodes that may have limited
2656/// functionality or require special handling in certain rendering contexts.
2657///
2658/// # Current Usage
2659///
2660/// Primarily used for [`ParseNodeColor`] nodes, which represent color changes
2661/// in mathematical expressions. These nodes may not be fully supported in all
2662/// output formats or rendering engines.
2663///
2664/// # Future Extensions
2665///
2666/// This type alias may be extended to include other command types that have
2667/// limited support or require special processing in the KaTeX rendering
2668/// pipeline.
2669///
2670/// # See Also
2671///
2672/// * [`ParseNodeColor`] - The color node type
2673pub type UnsupportedCmdParseNode = ParseNodeColor;
2674
2675/// Primary type alias for all parse nodes in the KaTeX AST.
2676///
2677/// This is the main type used throughout the KaTeX parsing and rendering
2678/// pipeline to represent mathematical expressions. It is equivalent to
2679/// [`AnyParseNode`] and provides a more convenient name for the core AST node
2680/// type.
2681///
2682/// # Architecture
2683///
2684/// The parse node system uses an enum-based approach where each variant
2685/// represents a different type of mathematical construct, from simple symbols
2686/// to complex structures like fractions and arrays.
2687///
2688/// # Usage
2689///
2690/// This type is used extensively in:
2691/// * Parser output - the result of parsing LaTeX input
2692/// * AST transformations - modifying or analyzing the parse tree
2693/// * Rendering pipeline - converting to visual output
2694/// * Type checking and validation - ensuring correct node types
2695///
2696/// # See Also
2697///
2698/// * [`AnyParseNode`] - The underlying enum type
2699/// * [`NodeType`] - Discriminant type for runtime type checking
2700/// * [`assert_node_type`] - Type assertion utility
2701pub type ParseNode = AnyParseNode;
2702
2703/// Errors that can occur during parse node validation and type checking.
2704///
2705/// This enum represents the various error conditions that can arise when
2706/// working with parse nodes, particularly during type assertions and
2707/// validation.
2708///
2709/// The error type implements [`std::error::Error`] and [`std::fmt::Display`]
2710/// for proper error handling and reporting throughout the KaTeX pipeline.
2711///
2712/// # Usage
2713///
2714/// These errors are typically returned by:
2715/// * [`assert_node_type`] - When type assertion fails
2716/// * [`assert_symbol_node_type`] - When symbol node assertion fails
2717///
2718/// They provide detailed information about what went wrong during node
2719/// validation, helping with debugging and error reporting in parsing and
2720/// rendering operations.
2721///
2722/// # Error Messages
2723///
2724/// Error messages are designed to be informative and include both the expected
2725/// and actual types to aid in troubleshooting type-related issues.
2726#[derive(Debug, Error, PartialEq, Eq)]
2727pub enum ParseNodeError {
2728 /// A node has an unexpected type during type checking
2729 #[error("Expected node of type {expected}, but got {actual}")]
2730 TypeMismatch {
2731 /// The expected [`NodeType`] that the node should have
2732 expected: NodeType,
2733 /// The actual type as a string representation
2734 actual: String,
2735 },
2736 /// A node is not one of the symbol node types
2737 #[error("Expected node of symbol group type, but got {actual}")]
2738 NotSymbolNode {
2739 /// The actual node type as a string
2740 actual: String,
2741 },
2742}
2743
2744/// Asserts that a parse node has the expected type and returns the node type.
2745///
2746/// This function performs runtime type checking on parse nodes, ensuring that
2747/// a node matches the expected [`NodeType`] before allowing further processing.
2748/// It's particularly useful when working with the dynamically-typed
2749/// [`AnyParseNode`] enum.
2750///
2751/// # Parameters
2752///
2753/// * `node` - An optional reference to the parse node to check
2754/// * `expected_type` - The expected [`NodeType`] that the node should have
2755///
2756/// # Returns
2757///
2758/// * `Ok(NodeType)` - The node type if the type matches
2759/// * `Err(ParseNodeError::TypeMismatch)` - If the node has a different type
2760/// * `Err(ParseNodeError::TypeMismatch)` - If `node` is `None` (with "null" as
2761/// actual type)
2762///
2763/// # Error Handling
2764///
2765/// The function provides detailed error information through [`ParseNodeError`],
2766/// including both the expected and actual types to aid in debugging.
2767///
2768/// # Performance
2769///
2770/// This function performs a simple discriminant check and string conversion,
2771/// making it suitable for use in performance-critical code paths.
2772///
2773/// # See Also
2774///
2775/// * [`NodeType`] - The enum of possible node types
2776/// * [`ParseNodeError`] - Error type returned on failure
2777/// * [`check_symbol_node_type`] - Check for symbol node types specifically
2778pub fn assert_node_type(
2779 node: Option<&AnyParseNode>,
2780 expected_type: NodeType,
2781) -> Result<NodeType, ParseNodeError> {
2782 let node = node.ok_or_else(|| ParseNodeError::TypeMismatch {
2783 expected: expected_type,
2784 actual: "null".to_owned(),
2785 })?;
2786
2787 let actual_type = NodeType::from(node);
2788
2789 if actual_type == expected_type {
2790 Ok(actual_type)
2791 } else {
2792 Err(ParseNodeError::TypeMismatch {
2793 expected: expected_type,
2794 actual: actual_type.to_string(),
2795 })
2796 }
2797}
2798
2799/// Checks if a parse node represents a symbol-type element and returns the node
2800/// type if so.
2801///
2802/// This function determines whether a given parse node belongs to the symbol
2803/// group, which includes atomic symbols, operators, ordinals, and other
2804/// fundamental mathematical elements that have specific spacing and rendering
2805/// properties.
2806///
2807/// # Symbol Node Types
2808///
2809/// The following [`AnyParseNode`] variants are considered symbol nodes:
2810/// * [`AnyParseNode::Atom`] - Atomic symbols with mathematical meaning
2811/// * [`AnyParseNode::MathOrd`] - Ordinary mathematical symbols
2812/// * [`AnyParseNode::Op`] - Mathematical operators
2813/// * [`AnyParseNode::Spacing`] - Explicit spacing elements
2814/// * [`AnyParseNode::TextOrd`] - Text symbols in math mode
2815/// * [`AnyParseNode::AccentToken`] - Accent symbol components
2816/// * [`AnyParseNode::OpToken`] - Operator symbol components
2817///
2818/// # Parameters
2819///
2820/// * `node` - An optional reference to the parse node to check
2821///
2822/// # Returns
2823///
2824/// * `Some(NodeType)` - The node type if it's a symbol node
2825/// * `None` - If the node is not a symbol node or if `node` is `None`
2826///
2827/// # Examples
2828///
2829/// Checking various node types:
2830/// ```rust
2831/// use katex::parser::parse_node::*;
2832/// use katex::symbols::Atom;
2833/// use katex::types::Mode;
2834///
2835/// // Symbol node - will return Some
2836/// let atom_node = AnyParseNode::Atom(ParseNodeAtom {
2837/// family: Atom::Bin,
2838/// mode: Mode::Math,
2839/// loc: None,
2840/// text: "+".to_string(),
2841/// });
2842/// assert!(check_symbol_node_type(Some(&atom_node)).is_some());
2843///
2844/// // Non-symbol node - will return None
2845/// let array_node = AnyParseNode::Array(ParseNodeArray {
2846/// mode: Mode::Math,
2847/// loc: None,
2848/// col_separation_type: None,
2849/// hskip_before_and_after: None,
2850/// add_jot: None,
2851/// cols: None,
2852/// arraystretch: 1.0,
2853/// body: vec![],
2854/// row_gaps: vec![],
2855/// h_lines_before_row: vec![],
2856/// tags: None,
2857/// leqno: None,
2858/// is_cd: None,
2859/// });
2860/// assert!(check_symbol_node_type(Some(&array_node)).is_none());
2861///
2862/// // None input - will return None
2863/// assert!(check_symbol_node_type(None).is_none());
2864/// ```
2865///
2866/// # Usage
2867///
2868/// This function is useful when you need to handle symbol nodes differently
2869/// from structural nodes (like arrays, fractions, etc.) in processing or
2870/// rendering logic.
2871///
2872/// # Performance
2873///
2874/// Uses a simple pattern match on the node variant, making it very efficient
2875/// for use in performance-critical code.
2876///
2877/// # See Also
2878///
2879/// * [`assert_symbol_node_type`] - Similar function that returns an error
2880/// instead of `None`
2881/// * [`SymbolParseNode`] - Type alias for symbol parse nodes
2882/// * [`assert_node_type`] - More general type checking function
2883#[must_use]
2884pub fn check_symbol_node_type(node: Option<&AnyParseNode>) -> Option<NodeType> {
2885 let node = node?;
2886
2887 // Check if this node is one of the symbol types
2888 match node {
2889 AnyParseNode::Atom(_)
2890 | AnyParseNode::MathOrd(_)
2891 | AnyParseNode::Spacing(_)
2892 | AnyParseNode::TextOrd(_)
2893 | AnyParseNode::AccentToken(_)
2894 | AnyParseNode::OpToken(_) => Some(NodeType::from(node)),
2895 _ => None,
2896 }
2897}
2898
2899/// Asserts that a parse node is a symbol-type element and returns the node
2900/// type, or returns an error.
2901///
2902/// This function is similar to [`check_symbol_node_type`] but returns a
2903/// [`ParseNodeError`] instead of `None` when the node is not a symbol type.
2904/// It's useful when you require a symbol node and want detailed error
2905/// information about why the assertion failed.
2906///
2907/// # Symbol Node Types
2908///
2909/// The following [`AnyParseNode`] variants are considered symbol nodes:
2910/// * [`AnyParseNode::Atom`] - Atomic symbols with mathematical meaning
2911/// * [`AnyParseNode::MathOrd`] - Ordinary mathematical symbols
2912/// * [`AnyParseNode::Op`] - Mathematical operators
2913/// * [`AnyParseNode::Spacing`] - Explicit spacing elements
2914/// * [`AnyParseNode::TextOrd`] - Text symbols in math mode
2915/// * [`AnyParseNode::AccentToken`] - Accent symbol components
2916/// * [`AnyParseNode::OpToken`] - Operator symbol components
2917///
2918/// # Parameters
2919///
2920/// * `node` - An optional reference to the parse node to check
2921///
2922/// # Returns
2923///
2924/// * `Ok(NodeType)` - The node type if it's a symbol node
2925/// * `Err(ParseNodeError::NotSymbolNode)` - If the node is not a symbol node
2926/// * `Err(ParseNodeError::NotSymbolNode)` - If `node` is `None` (with "null" as
2927/// the type)
2928///
2929/// # Error Handling
2930///
2931/// Provides detailed error information through
2932/// [`ParseNodeError::NotSymbolNode`], including the actual node type that was
2933/// encountered.
2934///
2935/// # Usage
2936///
2937/// Use this function when you need to ensure a node is a symbol type and want
2938/// to handle the error case explicitly, rather than just checking and
2939/// proceeding.
2940///
2941/// # Performance
2942///
2943/// Similar performance characteristics to [`check_symbol_node_type`], with the
2944/// added overhead of error construction on failure.
2945///
2946/// # See Also
2947///
2948/// * [`check_symbol_node_type`] - Non-panicking version that returns `Option`
2949/// * [`SymbolParseNode`] - Type alias for symbol parse nodes
2950/// * [`ParseNodeError`] - Error type returned on failure
2951pub fn assert_symbol_node_type(node: Option<&AnyParseNode>) -> Result<NodeType, ParseNodeError> {
2952 check_symbol_node_type(node).ok_or_else(|| {
2953 let actual = node.map_or_else(|| "null".to_owned(), |n| NodeType::from(n).to_string());
2954
2955 ParseNodeError::NotSymbolNode { actual }
2956 })
2957}
2958
2959#[cfg(test)]
2960mod tests {
2961 use super::*;
2962
2963 #[test]
2964 fn test_assert_node_type_success() {
2965 let node = AnyParseNode::Atom(ParseNodeAtom {
2966 family: Atom::Bin,
2967 mode: Mode::Math,
2968 loc: None,
2969 text: "+".to_owned(),
2970 });
2971
2972 let result = assert_node_type(Some(&node), NodeType::Atom);
2973 assert!(result.is_ok());
2974 assert_eq!(result.unwrap(), NodeType::Atom);
2975 }
2976
2977 #[test]
2978 fn test_assert_node_type_failure() {
2979 let node = AnyParseNode::Atom(ParseNodeAtom {
2980 family: Atom::Bin,
2981 mode: Mode::Math,
2982 loc: None,
2983 text: "+".to_owned(),
2984 });
2985
2986 let result = assert_node_type(Some(&node), NodeType::MathOrd);
2987 assert!(result.is_err());
2988 assert_eq!(
2989 result.unwrap_err(),
2990 ParseNodeError::TypeMismatch {
2991 expected: NodeType::MathOrd,
2992 actual: "atom".to_owned()
2993 }
2994 );
2995 }
2996
2997 #[test]
2998 fn test_assert_node_type_none() {
2999 let result = assert_node_type(None, NodeType::Atom);
3000 assert!(result.is_err());
3001 assert_eq!(
3002 result.unwrap_err(),
3003 ParseNodeError::TypeMismatch {
3004 expected: NodeType::Atom,
3005 actual: "null".to_owned()
3006 }
3007 );
3008 }
3009
3010 #[test]
3011 fn test_check_symbol_node_type_success() {
3012 let node = AnyParseNode::Atom(ParseNodeAtom {
3013 family: Atom::Bin,
3014 mode: Mode::Math,
3015 loc: None,
3016 text: "+".to_owned(),
3017 });
3018
3019 let result = check_symbol_node_type(Some(&node));
3020 assert!(result.is_some());
3021 }
3022
3023 #[test]
3024 fn test_check_symbol_node_type_failure() {
3025 let node = AnyParseNode::Array(ParseNodeArray {
3026 mode: Mode::Math,
3027 loc: None,
3028 col_separation_type: None,
3029 hskip_before_and_after: None,
3030 add_jot: None,
3031 cols: None,
3032 arraystretch: 1.0,
3033 body: vec![],
3034 row_gaps: vec![],
3035 h_lines_before_row: vec![],
3036 tags: None,
3037 leqno: None,
3038 is_cd: None,
3039 });
3040
3041 let result = check_symbol_node_type(Some(&node));
3042 assert!(result.is_none());
3043 }
3044
3045 #[test]
3046 fn test_assert_symbol_node_type_success() {
3047 let node = AnyParseNode::Atom(ParseNodeAtom {
3048 family: Atom::Bin,
3049 mode: Mode::Math,
3050 loc: None,
3051 text: "+".to_owned(),
3052 });
3053
3054 let result = assert_symbol_node_type(Some(&node));
3055 assert!(result.is_ok());
3056 }
3057
3058 #[test]
3059 fn test_assert_symbol_node_type_failure() {
3060 let node = AnyParseNode::Array(ParseNodeArray {
3061 mode: Mode::Math,
3062 loc: None,
3063 col_separation_type: None,
3064 hskip_before_and_after: None,
3065 add_jot: None,
3066 cols: None,
3067 arraystretch: 1.0,
3068 body: vec![],
3069 row_gaps: vec![],
3070 h_lines_before_row: vec![],
3071 tags: None,
3072 leqno: None,
3073 is_cd: None,
3074 });
3075
3076 let result = assert_symbol_node_type(Some(&node));
3077 assert!(result.is_err());
3078 assert_eq!(
3079 result.unwrap_err(),
3080 ParseNodeError::NotSymbolNode {
3081 actual: "array".to_owned()
3082 }
3083 );
3084 }
3085}