diff --git a/crates/math-core/src/character_class.rs b/crates/math-core/src/character_class.rs index 1cc556d3..fe83be80 100644 --- a/crates/math-core/src/character_class.rs +++ b/crates/math-core/src/character_class.rs @@ -1,3 +1,5 @@ +use mathml_renderer::attribute::TextTransform; + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum Class { /// `mathord` @@ -20,3 +22,36 @@ pub enum Class { /// A class indicating the end of the current formula. End, } + +#[derive(Debug, Clone, Copy)] +pub enum ParenType { + Left = 1, + Right, + Middle, +} + +/// mathvariant attribute +#[derive(Debug, Clone, Copy)] +pub enum MathVariant { + /// This is enforced by setting `mathvariant="normal"`. + Normal, + /// This is enforced by transforming the characters themselves. + Transform(TextTransform), +} + +#[cfg(test)] +mod tests { + use super::{MathVariant, TextTransform}; + + #[test] + fn size_test() { + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::() + ); + assert_eq!( + std::mem::size_of::>(), + std::mem::size_of::() + ); + } +} diff --git a/crates/math-core/src/commands.rs b/crates/math-core/src/commands.rs index eef6616b..9bf57553 100644 --- a/crates/math-core/src/commands.rs +++ b/crates/math-core/src/commands.rs @@ -1,8 +1,9 @@ use mathml_renderer::attribute::{ - FracAttr, HtmlTextStyle, MathVariant, Notation, OpAttrs, ParenType, Size, Style, TextTransform, + FracAttr, HtmlTextStyle, Notation, OpAttrs, Size, Style, TextTransform, }; use mathml_renderer::symbol::{self, Rel}; +use crate::character_class::{MathVariant, ParenType}; use crate::predefined; use crate::specifications::LatexUnit; use crate::token::{ @@ -40,10 +41,12 @@ static COMMANDS: phf::Map<&'static str, Token> = phf::phf_map! { "Beta" => UprightLetter(symbol::GREEK_CAPITAL_LETTER_BETA), "Big" => Big(Size::Scale2, None), "Bigg" => Big(Size::Scale4, None), - "Biggl" => Big(Size::Scale4, Some(ParenType::Open)), - "Biggr" => Big(Size::Scale4, Some(ParenType::Close)), - "Bigl" => Big(Size::Scale2, Some(ParenType::Open)), - "Bigr" => Big(Size::Scale2, Some(ParenType::Close)), + "Biggl" => Big(Size::Scale4, Some(ParenType::Left)), + "Biggm" => Big(Size::Scale4, Some(ParenType::Middle)), + "Biggr" => Big(Size::Scale4, Some(ParenType::Right)), + "Bigl" => Big(Size::Scale2, Some(ParenType::Left)), + "Bigm" => Big(Size::Scale2, Some(ParenType::Middle)), + "Bigr" => Big(Size::Scale2, Some(ParenType::Right)), "Box" => Letter(symbol::WHITE_MEDIUM_SQUARE, Mode::Math), "Bumpeq" => Relation(symbol::GEOMETRICALLY_EQUIVALENT_TO), "Cap" => BinaryOp(symbol::DOUBLE_INTERSECTION), @@ -169,13 +172,15 @@ static COMMANDS: phf::Map<&'static str, Token> = phf::phf_map! { "bigdoublevee" => Op(symbol::TWO_LOGICAL_OR_OPERATOR), "bigdoublewedge" => Op(symbol::TWO_LOGICAL_AND_OPERATOR), "bigg" => Big(Size::Scale3, None), - "biggl" => Big(Size::Scale3, Some(ParenType::Open)), - "biggr" => Big(Size::Scale3, Some(ParenType::Close)), - "bigl" => Big(Size::Scale1, Some(ParenType::Open)), + "biggl" => Big(Size::Scale3, Some(ParenType::Left)), + "biggm" => Big(Size::Scale3, Some(ParenType::Middle)), + "biggr" => Big(Size::Scale3, Some(ParenType::Right)), + "bigl" => Big(Size::Scale1, Some(ParenType::Left)), + "bigm" => Big(Size::Scale1, Some(ParenType::Middle)), "bigodot" => Op(symbol::N_ARY_CIRCLED_DOT_OPERATOR), "bigoplus" => Op(symbol::N_ARY_CIRCLED_PLUS_OPERATOR), "bigotimes" => Op(symbol::N_ARY_CIRCLED_TIMES_OPERATOR), - "bigr" => Big(Size::Scale1, Some(ParenType::Close)), + "bigr" => Big(Size::Scale1, Some(ParenType::Right)), "bigsqcap" => Op(symbol::N_ARY_SQUARE_INTERSECTION_OPERATOR), "bigsqcup" => Op(symbol::N_ARY_SQUARE_UNION_OPERATOR), "bigstar" => Letter(symbol::BLACK_STAR, Mode::Math), diff --git a/crates/math-core/src/parser.rs b/crates/math-core/src/parser.rs index e805007b..7939e99d 100644 --- a/crates/math-core/src/parser.rs +++ b/crates/math-core/src/parser.rs @@ -3,9 +3,7 @@ use std::{fmt::Write as _, mem, num::NonZeroU16, ops::Range}; use mathml_renderer::{ arena::{Arena, Buffer}, ast::Node, - attribute::{ - LetterAttr, MathSpacing, MathVariant, OpAttrs, ParenType, RowAttr, Style, TextTransform, - }, + attribute::{LetterAttr, MathSpacing, OpAttrs, RowAttr, Style, TextTransform}, length::Length, symbol::{ self, DelimiterSpacing, OpCategory, OrdCategory, RelCategory, StretchableOp, Stretchy, @@ -14,7 +12,7 @@ use mathml_renderer::{ use rustc_hash::FxHashMap; use crate::{ - character_class::Class, + character_class::{Class, MathVariant, ParenType}, color_defs::get_color, commands::get_negated_op, environments::{Env, NumberedEnvState}, @@ -390,7 +388,7 @@ where } ref tok @ (Token::Relation(relation) | Token::StretchyRel(relation)) => { class = Class::Relation; - let attr = match relation.category() { + let attrs = match relation.category() { // Category A relations are stretchy by default RelCategory::A => { // We let it be stretchy if it's explicitly marked as stretchy @@ -402,12 +400,13 @@ where } RelCategory::Default => OpAttrs::empty(), }; - let (left, right) = self.state.relation_spacing(prev_class, next_class); + let (left, right) = self.state.relation_spacing(prev_class, next_class, false); Ok(Node::Operator { op: relation.as_op(), - attrs: attr, + attrs, left, right, + size: None, }) } Token::Punctuation(punc) => { @@ -422,6 +421,7 @@ where attrs: OpAttrs::empty(), left: None, right, + size: None, }) } Token::ForcePunctuation(op) => { @@ -436,10 +436,11 @@ where attrs: OpAttrs::empty(), left: Some(MathSpacing::Zero), right, + size: None, }) } Token::Ord(ord) => { - let attr = if matches!(ord.category(), OrdCategory::FGandForceDefault) { + let attrs = if matches!(ord.category(), OrdCategory::FGandForceDefault) { // Category F+G operators will stretch in pre- and postfix positions, // so we explicitly set the stretchy attribute to false to prevent that. // Alternatively, we could set `form="infix"` on them. @@ -459,9 +460,10 @@ where }; Ok(Node::Operator { op: ord.as_op(), - attrs: attr, + attrs, left, right, + size: None, }) } Token::BinaryOp(binary_op) => { @@ -477,6 +479,7 @@ where attrs: OpAttrs::empty(), left: spacing, right: spacing, + size: None, }) } Token::ForceBinaryOp(op) => { @@ -489,6 +492,7 @@ where attrs: OpAttrs::empty(), left: spacing, right: spacing, + size: None, }) } Token::Mathbin => 'mathbin: { @@ -531,6 +535,7 @@ where attrs: OpAttrs::STRETCHY_FALSE, left: spacing, right: spacing, + size: None, }) } Token::Inner(op) => { @@ -563,10 +568,11 @@ where attrs: OpAttrs::empty(), left, right, + size: None, }) } Token::OpGreaterThan => { - let (left, right) = self.state.relation_spacing(prev_class, next_class); + let (left, right) = self.state.relation_spacing(prev_class, next_class, false); class = Class::Relation; Ok(Node::PseudoOp { name: ">", @@ -576,7 +582,7 @@ where }) } Token::OpLessThan => { - let (left, right) = self.state.relation_spacing(prev_class, next_class); + let (left, right) = self.state.relation_spacing(prev_class, next_class, false); class = Class::Relation; Ok(Node::PseudoOp { name: "<", @@ -766,6 +772,7 @@ where attrs: OpAttrs::empty(), left: None, right: None, + size: None, }); let base = if is_over { Node::Over { symbol, target } @@ -808,16 +815,17 @@ where Bounds(None, None) }; let (left, right) = self.big_operator_spacing(parse_as, prev_class, false)?; - let attr = if has_movable_limits && limits { + let attrs = if has_movable_limits && limits { OpAttrs::NO_MOVABLE_LIMITS } else { OpAttrs::empty() }; let target = self.commit(Node::Operator { op: op.as_op(), - attrs: attr, + attrs, left, right, + size: None, }); let use_underover = has_movable_limits || limits; if use_underover { @@ -903,13 +911,15 @@ where let next_class = self.tokens.peek_class_token(parse_as.in_sequence())?; match tok { Token::Relation(op) => { - let (left, right) = self.state.relation_spacing(prev_class, next_class); + let (left, right) = + self.state.relation_spacing(prev_class, next_class, false); if let Some(negated) = get_negated_op(op) { Ok(Node::Operator { op: negated.as_op(), attrs: OpAttrs::empty(), left, right, + size: None, }) } else { Ok(Node::Operator { @@ -917,11 +927,13 @@ where attrs: OpAttrs::empty(), left, right, + size: None, }) } } tok @ (Token::OpLessThan | Token::OpGreaterThan) => { - let (left, right) = self.state.relation_spacing(prev_class, next_class); + let (left, right) = + self.state.relation_spacing(prev_class, next_class, false); Ok(Node::Operator { op: if matches!(tok, Token::OpLessThan) { symbol::NOT_LESS_THAN.as_op() @@ -931,6 +943,7 @@ where attrs: OpAttrs::empty(), left, right, + size: None, }) } // We have to special-case `\exists` here because it is not a relation. @@ -939,6 +952,7 @@ where attrs: OpAttrs::empty(), left: None, right: None, + size: None, }), Token::Letter(char, _) | Token::UprightLetter(char) => { let mut builder = self.buffer.get_builder(); @@ -961,12 +975,7 @@ where Token::ForceRelation(op) => { class = Class::Relation; let (left, right) = if parse_as.in_sequence() { - let (left, right) = self.state.relation_spacing(prev_class, next_class); - // We have to turn `None` into explicit relation spacing. - ( - left.or(Some(MathSpacing::FiveMu)), - right.or(Some(MathSpacing::FiveMu)), - ) + self.state.relation_spacing(prev_class, next_class, true) } else { // Don't add spacing if we are in an argument. (None, None) @@ -976,6 +985,7 @@ where attrs: OpAttrs::empty(), left, right, + size: None, }) } Token::ForceClose(op) => { @@ -985,6 +995,7 @@ where attrs: OpAttrs::empty(), left: None, right: None, + size: None, }) } Token::GroupBegin => { @@ -1007,7 +1018,7 @@ where if open { class = Class::Open; } - let mut attr = if matches!(paren.category(), OrdCategory::FGandForceDefault) { + let mut attrs = if matches!(paren.category(), OrdCategory::FGandForceDefault) { // For this category of symbol, we have to force the form attribute // in order to get correct spacing. if open { @@ -1024,13 +1035,14 @@ where ) { // Symbols from these categories are automatically stretchy, // so we have to explicitly disable that here. - attr |= OpAttrs::STRETCHY_FALSE; + attrs |= OpAttrs::STRETCHY_FALSE; } Ok(Node::Operator { op: paren.as_op(), - attrs: attr, + attrs, left: None, right: None, + size: None, }) } Token::SquareBracketOpen => { @@ -1040,6 +1052,7 @@ where attrs: OpAttrs::STRETCHY_FALSE, left: None, right: None, + size: None, }) } Token::SquareBracketClose => Ok(Node::Operator { @@ -1047,6 +1060,7 @@ where attrs: OpAttrs::STRETCHY_FALSE, left: None, right: None, + size: None, }), Token::Left => { let tok_loc = self.next_token()?; @@ -1088,6 +1102,7 @@ where attrs: middle_stretch_attrs(op), left: spacing, right: spacing, + size: None, }) } Token::Big(size, paren_type) => { @@ -1095,11 +1110,68 @@ where let paren = extract_delimiter(tok_loc, DelimiterModifier::Big)?; // `\big` commands without the "l" or "r" really produce `Class::Default`. class = match paren_type { - Some(ParenType::Open) => Class::Open, - Some(ParenType::Close) => Class::Close, + Some(ParenType::Left) => Class::Open, + Some(ParenType::Right) => Class::Close, + Some(ParenType::Middle) => Class::Relation, None => Class::Default, }; - Ok(Node::SizedParen(size, paren, paren_type)) + // Convert stretchy property to OpAttrs. + let mut attrs = match paren.stretchy { + Stretchy::PrePostfix | Stretchy::Never => { + OpAttrs::STRETCHY_TRUE | OpAttrs::SYMMETRIC_TRUE + } + Stretchy::AlwaysAsymmetric => OpAttrs::SYMMETRIC_TRUE, + Stretchy::Always => OpAttrs::empty(), + }; + // Determine form and spacing attributes based on paren_type + // and delimiter spacing. + let (left, right) = if matches!(paren_type, Some(ParenType::Middle)) { + // We need to achieve relation spacing here. + let next_class = self.tokens.peek_class_token(parse_as.in_sequence())?; + if matches!(paren.spacing, DelimiterSpacing::InfixRelation) { + attrs |= OpAttrs::FORM_INFIX; + } + self.state.relation_spacing( + prev_class, + next_class, + !matches!( + paren.spacing, + DelimiterSpacing::InfixRelation | DelimiterSpacing::Relation + ), + ) + } else { + // We need to achieve open/close spacing here (i.e., zero spacing) + // If the delimiter has relation spacing only in infix positions, then we can + // get spacing to zero by setting the form attributes. + if let Some(paren_type) = paren_type + && matches!(paren.spacing, DelimiterSpacing::InfixRelation) + { + // We already handled the spacing for middle delimiters above, so we only + // need to set the form attributes for left and right delimiters here. + if matches!(paren_type, ParenType::Left) { + attrs |= OpAttrs::FORM_PREFIX; + } else { + attrs |= OpAttrs::FORM_POSTFIX; + } + (None, None) + } else if matches!( + paren.spacing, + DelimiterSpacing::InfixRelation + | DelimiterSpacing::Relation + | DelimiterSpacing::Other + ) { + (Some(MathSpacing::Zero), Some(MathSpacing::Zero)) + } else { + (None, None) + } + }; + Ok(Node::Operator { + op: paren.as_op(), + attrs, + size: Some(size), + left, + right, + }) } Token::Begin(env) => 'begin_env: { let array_spec = if matches!(env, Env::Array | Env::Subarray) { @@ -1329,6 +1401,7 @@ where attrs: OpAttrs::empty(), left: None, right: None, + size: None, }); Ok(Node::Sup { target, symbol }) } @@ -1553,6 +1626,7 @@ where attrs: OpAttrs::empty(), left: None, right: None, + size: None, })); } else { for _ in 0..prime_count { @@ -1561,6 +1635,7 @@ where attrs: OpAttrs::empty(), left: None, right: None, + size: None, })); } } @@ -1769,6 +1844,7 @@ impl ParserState<'_, '_> { &self, prev_class: Class, next_class: Class, + force: bool, ) -> (Option, Option) { ( if matches!( @@ -1777,6 +1853,8 @@ impl ParserState<'_, '_> { ) || self.script_style { Some(MathSpacing::Zero) + } else if force { + Some(MathSpacing::FiveMu) // force relation spacing } else { None }, @@ -1786,6 +1864,8 @@ impl ParserState<'_, '_> { ) || self.script_style { Some(MathSpacing::Zero) + } else if force { + Some(MathSpacing::FiveMu) // force relation spacing } else { None }, @@ -1830,18 +1910,13 @@ pub(crate) fn node_vec_to_node<'arena>( ) -> &'arena Node<'arena> { if let [single] = nodes { if reset_spacing { - if let Node::Operator { - op, - attrs: attr, - left: _, - right: _, - } = single - { + if let Node::Operator { op, attrs, .. } = single { arena.push(Node::Operator { op: *op, - attrs: *attr, + attrs: *attrs, left: None, right: None, + size: None, }) } else { single diff --git a/crates/math-core/src/predefined.rs b/crates/math-core/src/predefined.rs index 119e89df..07407cb4 100644 --- a/crates/math-core/src/predefined.rs +++ b/crates/math-core/src/predefined.rs @@ -1,5 +1,6 @@ -use mathml_renderer::{attribute::MathVariant, symbol}; +use mathml_renderer::symbol; +use crate::character_class::MathVariant; use crate::specifications::LatexUnit; use crate::token::Mode; use crate::token::Token::{self, *}; diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__big_paren.snap b/crates/math-core/src/snapshots/math_core__parser__tests__big_paren.snap index 59d4f92d..0ae4ca01 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__big_paren.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__big_paren.snap @@ -3,5 +3,11 @@ source: crates/math-core/src/parser.rs expression: "\\big(" --- [ - SizedParen(Scale1, StretchableOp('(', Always), None), + Operator( + op: '(', + attrs: OpAttrs(""), + size: Some(Scale1), + left: None, + right: None, + ), ] diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_in_subscript.snap b/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_in_subscript.snap index e1cfa9d6..5306de3d 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_in_subscript.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_in_subscript.snap @@ -8,6 +8,7 @@ expression: "x_:\\equiv, x_:=" symbol: Operator( op: ':', attrs: OpAttrs(""), + size: None, left: None, right: None, ), @@ -15,12 +16,14 @@ expression: "x_:\\equiv, x_:=" Operator( op: '≡', attrs: OpAttrs(""), + size: None, left: None, right: Some(Zero), ), Operator( op: ',', attrs: OpAttrs(""), + size: None, left: None, right: None, ), @@ -29,6 +32,7 @@ expression: "x_:\\equiv, x_:=" symbol: Operator( op: ':', attrs: OpAttrs(""), + size: None, left: None, right: None, ), @@ -36,6 +40,7 @@ expression: "x_:\\equiv, x_:=" Operator( op: '=', attrs: OpAttrs(""), + size: None, left: None, right: Some(Zero), ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_stop.snap b/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_stop.snap index 50627dbb..13890c1e 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_stop.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__colon_fusion_stop.snap @@ -6,6 +6,7 @@ expression: ":2=:=" Operator( op: ':', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(FiveMu), ), @@ -13,18 +14,21 @@ expression: ":2=:=" Operator( op: '=', attrs: OpAttrs(""), + size: None, left: None, right: Some(Zero), ), Operator( op: ':', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), Operator( op: '=', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_end.snap b/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_end.snap index b8e64736..342612d1 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_end.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_end.snap @@ -10,6 +10,7 @@ expression: "\\begin{matrix}\\sum\\displaystyle\\sum\\end{matrix}" Operator( op: '∑', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: None, ), @@ -18,6 +19,7 @@ expression: "\\begin{matrix}\\sum\\displaystyle\\sum\\end{matrix}" Operator( op: '∑', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_right.snap b/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_right.snap index 204bde33..575715ca 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_right.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__displaystyle_ended_by_right.snap @@ -12,6 +12,7 @@ expression: "\\left(\\displaystyle \\int\\right)\\int" Operator( op: '∫', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), @@ -22,6 +23,7 @@ expression: "\\left(\\displaystyle \\int\\right)\\int" Operator( op: '∫', attrs: OpAttrs(""), + size: None, left: None, right: Some(Zero), ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__double_prime.snap b/crates/math-core/src/snapshots/math_core__parser__tests__double_prime.snap index 2110604f..5364d380 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__double_prime.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__double_prime.snap @@ -8,6 +8,7 @@ expression: "f''" symbol: Operator( op: '″', attrs: OpAttrs(""), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__int_bounds_relation.snap b/crates/math-core/src/snapshots/math_core__parser__tests__int_bounds_relation.snap index b7d9b52c..bdee00e1 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__int_bounds_relation.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__int_bounds_relation.snap @@ -9,6 +9,7 @@ expression: "{\\int_0^\\infty = 4}" target: Operator( op: '∫', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), @@ -18,6 +19,7 @@ expression: "{\\int_0^\\infty = 4}" Operator( op: '=', attrs: OpAttrs(""), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__int_relation.snap b/crates/math-core/src/snapshots/math_core__parser__tests__int_relation.snap index 2087294e..c7272a50 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__int_relation.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__int_relation.snap @@ -8,12 +8,14 @@ expression: "{\\int = 4}" Operator( op: '∫', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), Operator( op: '=', attrs: OpAttrs(""), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__integral_with_reversed_limits.snap b/crates/math-core/src/snapshots/math_core__parser__tests__integral_with_reversed_limits.snap index 2fb8c237..97eebf35 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__integral_with_reversed_limits.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__integral_with_reversed_limits.snap @@ -7,6 +7,7 @@ expression: "\\int\\limits^1_0 dx" target: Operator( op: '∫', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__number_after_lim.snap b/crates/math-core/src/snapshots/math_core__parser__tests__number_after_lim.snap index 2cd0ca98..55fda16c 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__number_after_lim.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__number_after_lim.snap @@ -8,6 +8,7 @@ expression: "\\sum\\limits_12" target: Operator( op: '∑', attrs: OpAttrs("NO_MOVABLE_LIMITS"), + size: None, left: Some(Zero), right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__number_after_overbrace.snap b/crates/math-core/src/snapshots/math_core__parser__tests__number_after_overbrace.snap index e05d36cd..9e09d42c 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__number_after_overbrace.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__number_after_overbrace.snap @@ -7,6 +7,7 @@ expression: "\\overbrace12" symbol: Operator( op: '⏞', attrs: OpAttrs(""), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__number_with_spaces_with_dots.snap b/crates/math-core/src/snapshots/math_core__parser__tests__number_with_spaces_with_dots.snap index fbc9a3bb..24e3cc3d 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__number_with_spaces_with_dots.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__number_with_spaces_with_dots.snap @@ -7,6 +7,7 @@ expression: "1 2. 3 , 4" Operator( op: ',', attrs: OpAttrs(""), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__pmod_subscript.snap b/crates/math-core/src/snapshots/math_core__parser__tests__pmod_subscript.snap index ca2a73c1..a8cf404d 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__pmod_subscript.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__pmod_subscript.snap @@ -10,6 +10,7 @@ expression: "\\pmod{3}_4" Operator( op: '(', attrs: OpAttrs("STRETCHY_FALSE"), + size: None, left: None, right: None, ), @@ -23,6 +24,7 @@ expression: "\\pmod{3}_4" target: Operator( op: ')', attrs: OpAttrs("STRETCHY_FALSE"), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__sub_big_paren.snap b/crates/math-core/src/snapshots/math_core__parser__tests__sub_big_paren.snap index 79cc6f95..b02a946f 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__sub_big_paren.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__sub_big_paren.snap @@ -5,6 +5,12 @@ expression: "x_\\big(" [ Sub( target: IdentifierChar('x', Default), - symbol: SizedParen(Scale1, StretchableOp('(', Always), None), + symbol: Operator( + op: '(', + attrs: OpAttrs(""), + size: Some(Scale1), + left: None, + right: None, + ), ), ] diff --git a/crates/math-core/src/snapshots/math_core__parser__tests__sum_relation.snap b/crates/math-core/src/snapshots/math_core__parser__tests__sum_relation.snap index c3110a0d..3cb7182b 100644 --- a/crates/math-core/src/snapshots/math_core__parser__tests__sum_relation.snap +++ b/crates/math-core/src/snapshots/math_core__parser__tests__sum_relation.snap @@ -8,12 +8,14 @@ expression: "{\\sum = 4}" Operator( op: '∑', attrs: OpAttrs(""), + size: None, left: Some(Zero), right: Some(Zero), ), Operator( op: '=', attrs: OpAttrs(""), + size: None, left: None, right: None, ), diff --git a/crates/math-core/src/token.rs b/crates/math-core/src/token.rs index 29c4f66b..4d594b9b 100644 --- a/crates/math-core/src/token.rs +++ b/crates/math-core/src/token.rs @@ -2,13 +2,11 @@ use std::ops::Range; use strum_macros::IntoStaticStr; -use mathml_renderer::attribute::{ - FracAttr, HtmlTextStyle, MathVariant, Notation, OpAttrs, ParenType, Size, Style, -}; +use mathml_renderer::attribute::{FracAttr, HtmlTextStyle, Notation, OpAttrs, Size, Style}; use mathml_renderer::length::Length; use mathml_renderer::symbol::{Bin, MathMLOperator, Op, OrdLike, Punct, Rel}; -use crate::character_class::Class; +use crate::character_class::{Class, MathVariant, ParenType}; use crate::environments::Env; #[derive(Debug, Clone, Copy)] @@ -213,10 +211,10 @@ impl Token<'_> { } End(_) | NewLine | NewColumn | GroupEnd | Eoi => Some(Class::End), Inner(_) => Some(Class::Inner), - Big(_, Some(paren_type)) => Some(if matches!(paren_type, ParenType::Open) { - Class::Open - } else { - Class::Close + Big(_, Some(paren_type)) => Some(match paren_type { + ParenType::Left => Class::Open, + ParenType::Right => Class::Close, + ParenType::Middle => Class::Relation, }), CustomCmd(_, toks) => toks.iter().find_map(Token::class), Whitespace | Space(_) | Not | TransformSwitch(_) | NoNumber | Tag | CustomSpace diff --git a/crates/math-core/tests/conversion_test.rs b/crates/math-core/tests/conversion_test.rs index 5c47d943..f2f7fbda 100644 --- a/crates/math-core/tests/conversion_test.rs +++ b/crates/math-core/tests/conversion_test.rs @@ -329,6 +329,10 @@ fn main() { ("bigl_pipe", r"\bigl| x \bigr|"), ("big_pipe", r"\big| x \big|"), ("bigl_double_pipe", r"\bigl\| x \bigr\|"), + ("bigm_pipe", r"2+\bigm|)"), + ("bigm_close_paren", r"2+\bigm()"), + ("bigm_uparrow", r"x\bigm\uparrow x"), + ("bigm_slash", r"x\bigm/ x"), ("plus_after_sum", r"\sum + 4"), ("plus_before_sum", r"4 + \sum"), ("plus_after_equal_subscript", r"x =_+4"), diff --git a/crates/math-core/tests/snapshots/conversion_test__big_pipe.snap b/crates/math-core/tests/snapshots/conversion_test__big_pipe.snap index a215e368..8457d3ff 100644 --- a/crates/math-core/tests/snapshots/conversion_test__big_pipe.snap +++ b/crates/math-core/tests/snapshots/conversion_test__big_pipe.snap @@ -3,7 +3,7 @@ source: crates/math-core/tests/conversion_test.rs expression: "\\big| x \\big|" --- - | + | x - | + | diff --git a/crates/math-core/tests/snapshots/conversion_test__bigl_double_pipe.snap b/crates/math-core/tests/snapshots/conversion_test__bigl_double_pipe.snap index 9c1c713d..b3585172 100644 --- a/crates/math-core/tests/snapshots/conversion_test__bigl_double_pipe.snap +++ b/crates/math-core/tests/snapshots/conversion_test__bigl_double_pipe.snap @@ -3,7 +3,7 @@ source: crates/math-core/tests/conversion_test.rs expression: "\\bigl\\| x \\bigr\\|" --- - + x - + diff --git a/crates/math-core/tests/snapshots/conversion_test__bigl_pipe.snap b/crates/math-core/tests/snapshots/conversion_test__bigl_pipe.snap index a60d5764..40963553 100644 --- a/crates/math-core/tests/snapshots/conversion_test__bigl_pipe.snap +++ b/crates/math-core/tests/snapshots/conversion_test__bigl_pipe.snap @@ -3,7 +3,7 @@ source: crates/math-core/tests/conversion_test.rs expression: "\\bigl| x \\bigr|" --- - | + | x - | + | diff --git a/crates/math-core/tests/snapshots/conversion_test__bigm_close_paren.snap b/crates/math-core/tests/snapshots/conversion_test__bigm_close_paren.snap new file mode 100644 index 00000000..70f5791c --- /dev/null +++ b/crates/math-core/tests/snapshots/conversion_test__bigm_close_paren.snap @@ -0,0 +1,10 @@ +--- +source: crates/math-core/tests/conversion_test.rs +expression: "2+\\bigm()" +--- + + 2 + + + ( + ) + diff --git a/crates/math-core/tests/snapshots/conversion_test__bigm_pipe.snap b/crates/math-core/tests/snapshots/conversion_test__bigm_pipe.snap new file mode 100644 index 00000000..ee4a20c3 --- /dev/null +++ b/crates/math-core/tests/snapshots/conversion_test__bigm_pipe.snap @@ -0,0 +1,10 @@ +--- +source: crates/math-core/tests/conversion_test.rs +expression: "2+\\bigm|)" +--- + + 2 + + + | + ) + diff --git a/crates/math-core/tests/snapshots/conversion_test__bigm_slash.snap b/crates/math-core/tests/snapshots/conversion_test__bigm_slash.snap new file mode 100644 index 00000000..6b47ca94 --- /dev/null +++ b/crates/math-core/tests/snapshots/conversion_test__bigm_slash.snap @@ -0,0 +1,9 @@ +--- +source: crates/math-core/tests/conversion_test.rs +expression: "x\\bigm/ x" +--- + + x + / + x + diff --git a/crates/math-core/tests/snapshots/conversion_test__bigm_uparrow.snap b/crates/math-core/tests/snapshots/conversion_test__bigm_uparrow.snap new file mode 100644 index 00000000..da7cd335 --- /dev/null +++ b/crates/math-core/tests/snapshots/conversion_test__bigm_uparrow.snap @@ -0,0 +1,9 @@ +--- +source: crates/math-core/tests/conversion_test.rs +expression: "x\\bigm\\uparrow x" +--- + + x + + x + diff --git a/crates/math-core/tests/snapshots/conversion_test__log_in_big.snap b/crates/math-core/tests/snapshots/conversion_test__log_in_big.snap index f1ff5b96..a020d0af 100644 --- a/crates/math-core/tests/snapshots/conversion_test__log_in_big.snap +++ b/crates/math-core/tests/snapshots/conversion_test__log_in_big.snap @@ -3,11 +3,11 @@ source: crates/math-core/tests/conversion_test.rs expression: "\\bigl(\\log\\bigr) + \\big(\\log\\big)" --- - ( + ( log - ) + ) + - ( + ( log - ) + ) diff --git a/crates/math-core/tests/snapshots/conversion_test__plus_after_bigl.snap b/crates/math-core/tests/snapshots/conversion_test__plus_after_bigl.snap index 8374d79b..8c15a91f 100644 --- a/crates/math-core/tests/snapshots/conversion_test__plus_after_bigl.snap +++ b/crates/math-core/tests/snapshots/conversion_test__plus_after_bigl.snap @@ -3,7 +3,7 @@ source: crates/math-core/tests/conversion_test.rs expression: "\\bigl)+ x" --- - ) + ) + x diff --git a/crates/math-core/tests/snapshots/conversion_test__plus_after_bigr.snap b/crates/math-core/tests/snapshots/conversion_test__plus_after_bigr.snap index 293e66be..fb04acf8 100644 --- a/crates/math-core/tests/snapshots/conversion_test__plus_after_bigr.snap +++ b/crates/math-core/tests/snapshots/conversion_test__plus_after_bigr.snap @@ -3,7 +3,7 @@ source: crates/math-core/tests/conversion_test.rs expression: "\\bigr(+ x" --- - ( + ( + x diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki145.snap b/crates/math-core/tests/snapshots/wiki_test__wiki145.snap index 4d0b3a8d..73f20516 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki145.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki145.snap @@ -4,16 +4,16 @@ expression: "( \\bigl( \\Bigl( \\biggl( \\Biggl( \\dots \\Biggr] \\biggr] \\Bigr --- ( - ( - ( - ( - ( + ( + ( + ( + ( . . . - ] - ] - ] - ] + ] + ] + ] + ] ] diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki146.snap b/crates/math-core/tests/snapshots/wiki_test__wiki146.snap index 0293a4fb..f5a80414 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki146.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki146.snap @@ -4,16 +4,16 @@ expression: "\\{ \\bigl\\{ \\Bigl\\{ \\biggl\\{ \\Biggl\\{ \\dots \\Biggr\\rangl --- { - { - { - { - { + { + { + { + { . . . - - - - + + + + diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki147.snap b/crates/math-core/tests/snapshots/wiki_test__wiki147.snap index cf9e7ab8..cb7dc4a9 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki147.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki147.snap @@ -4,16 +4,16 @@ expression: "\\| \\big\\| \\Big\\| \\bigg\\| \\Bigg\\| \\dots \\Bigg| \\bigg| \\ --- - - - - + + + + . . . - | - | - | - | + | + | + | + | | diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki148.snap b/crates/math-core/tests/snapshots/wiki_test__wiki148.snap index 9f18b8ab..b761e4e9 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki148.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki148.snap @@ -4,16 +4,16 @@ expression: "\\lfloor \\bigl\\lfloor \\Bigl\\lfloor \\biggl\\lfloor \\Biggl\\lfl --- - - - - + + + + . . . - - - - + + + + diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki149.snap b/crates/math-core/tests/snapshots/wiki_test__wiki149.snap index 67106814..e259fa6e 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki149.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki149.snap @@ -4,16 +4,16 @@ expression: "\\uparrow \\big\\uparrow \\Big\\uparrow \\bigg\\uparrow \\Bigg\\upa --- - - - - + + + + . . . - - - - + + + + diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki150.snap b/crates/math-core/tests/snapshots/wiki_test__wiki150.snap index 31de41c2..a6c3b154 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki150.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki150.snap @@ -4,16 +4,16 @@ expression: "\\updownarrow\\big\\updownarrow\\Big\\updownarrow \\bigg\\updownarr --- - - - - + + + + . . . - - - - + + + + diff --git a/crates/math-core/tests/snapshots/wiki_test__wiki151.snap b/crates/math-core/tests/snapshots/wiki_test__wiki151.snap index 238a5f1a..0df5e7b3 100644 --- a/crates/math-core/tests/snapshots/wiki_test__wiki151.snap +++ b/crates/math-core/tests/snapshots/wiki_test__wiki151.snap @@ -4,16 +4,16 @@ expression: "/ \\big/ \\Big/ \\bigg/ \\Bigg/ \\dots \\Bigg\\backslash \\bigg\\ba --- / - / - / - / - / + / + / + / + / . . . - \ - \ - \ - \ + \ + \ + \ + \ \ diff --git a/crates/mathml-renderer/src/ast.rs b/crates/mathml-renderer/src/ast.rs index 059a87c5..f9d986a5 100644 --- a/crates/mathml-renderer/src/ast.rs +++ b/crates/mathml-renderer/src/ast.rs @@ -5,13 +5,12 @@ use std::num::NonZeroU16; use serde::Serialize; use crate::attribute::{ - FracAttr, HtmlTextStyle, LetterAttr, MathSpacing, Notation, OpAttrs, ParenType, RowAttr, Size, - Style, + FracAttr, HtmlTextStyle, LetterAttr, MathSpacing, Notation, OpAttrs, RowAttr, Size, Style, }; use crate::fmt::new_line_and_indent; use crate::itoa::append_u8_as_hex; use crate::length::{Length, LengthUnit, LengthValue}; -use crate::symbol::{DelimiterSpacing, MathMLOperator, StretchableOp, Stretchy}; +use crate::symbol::{MathMLOperator, StretchableOp, Stretchy}; use crate::table::{Alignment, ArraySpec, ColumnGenerator, LineType, RIGHT_ALIGN}; /// AST node @@ -28,6 +27,7 @@ pub enum Node<'arena> { Operator { op: MathMLOperator, attrs: OpAttrs, + size: Option, left: Option, right: Option, }, @@ -102,7 +102,6 @@ pub enum Node<'arena> { close: Option, content: &'arena Node<'arena>, }, - SizedParen(Size, StretchableOp, Option), /// `...` Text(Option, &'arena str), /// `...` for matrices and similar constructs @@ -197,21 +196,30 @@ impl Node<'_> { } Node::Operator { op, - attrs: attr, + attrs, left, right, + size, } => { - emit_operator_attributes(s, *attr, *left, *right)?; + emit_operator_attributes(s, *attrs, *left, *right)?; + if let Some(size) = size { + write!( + s, + " minsize=\"{}\" maxsize=\"{}\"", + <&str>::from(size), + <&str>::from(size), + )?; + } write!(s, ">{}", char::from(op))?; } Node::PseudoOp { - attrs: attr, + attrs, left, right, - name: text, + name, } => { - emit_operator_attributes(s, *attr, *left, *right)?; - write!(s, ">{text}")?; + emit_operator_attributes(s, *attrs, *left, *right)?; + write!(s, ">{name}")?; } node @ (Node::IdentifierStr(letters) | Node::Text(_, letters)) => { let (open, close) = match node { @@ -410,34 +418,6 @@ impl Node<'_> { emit_fence(s, *close, OpAttrs::empty())?; writeln_indent!(s, base_indent, ""); } - Node::SizedParen(size, paren, paren_type) => { - write!( - s, - "::from(size), - <&str>::from(size) - )?; - match paren.stretchy { - Stretchy::PrePostfix | Stretchy::Never => { - write!(s, " stretchy=\"true\" symmetric=\"true\"")?; - } - Stretchy::AlwaysAsymmetric => { - write!(s, " symmetric=\"true\"")?; - } - Stretchy::Always => {} - } - if let Some(paren_type) = paren_type - && matches!(paren.spacing, DelimiterSpacing::InfixNonZero) - { - write!(s, "{}", <&str>::from(paren_type))?; - } else if matches!( - paren.spacing, - DelimiterSpacing::InfixNonZero | DelimiterSpacing::NonZero - ) { - write!(s, " lspace=\"0\" rspace=\"0\"")?; - } - write!(s, ">{}", char::from(*paren))?; - } Node::Slashed(node) => match node { Node::IdentifierChar(x, attr) => { if matches!(attr, LetterAttr::ForcedUpright) { @@ -826,6 +806,7 @@ mod tests { attrs: OpAttrs::empty(), left: Some(MathSpacing::FourMu), right: Some(MathSpacing::FourMu), + size: None, }), ":" ); @@ -835,6 +816,7 @@ mod tests { attrs: OpAttrs::empty(), left: Some(MathSpacing::FourMu), right: Some(MathSpacing::Zero), + size: None, }), ":" ); @@ -844,6 +826,7 @@ mod tests { attrs: OpAttrs::empty(), left: Some(MathSpacing::Zero), right: None, + size: None, }), "" ); @@ -853,6 +836,7 @@ mod tests { attrs: OpAttrs::FORM_PREFIX, left: None, right: None, + size: None, }), "+" ); @@ -862,6 +846,7 @@ mod tests { attrs: OpAttrs::NO_MOVABLE_LIMITS, left: None, right: None, + size: None, }), "" ); @@ -970,13 +955,15 @@ mod tests { op: symbol::EXCLAMATION_MARK, attrs: OpAttrs::empty(), left: None, - right: None + right: None, + size: None, }, target: &Node::Operator { op: symbol::EQUALS_SIGN.as_op(), attrs: OpAttrs::empty(), left: None, - right: None + right: None, + size: None, }, }), "=!" @@ -1129,6 +1116,7 @@ mod tests { attrs: OpAttrs::empty(), left: None, right: None, + size: None, }, &Node::Number("1"), ]; @@ -1156,22 +1144,29 @@ mod tests { } #[test] - fn render_sized_paren() { + fn render_sized_operator() { assert_eq!( - render(&Node::SizedParen( - Size::Scale1, - symbol::LEFT_PARENTHESIS.as_stretchable_op().unwrap(), - None, - )), - "(" + render(&Node::Operator { + op: symbol::LEFT_PARENTHESIS + .as_stretchable_op() + .unwrap() + .as_op(), + attrs: OpAttrs::empty(), + size: Some(Size::Scale1), + left: None, + right: None, + }), + "(" ); assert_eq!( - render(&Node::SizedParen( - Size::Scale3, - symbol::SOLIDUS.as_stretchable_op().unwrap(), - None, - )), - "/" + render(&Node::Operator { + op: symbol::SOLIDUS.as_stretchable_op().unwrap().as_op(), + attrs: OpAttrs::STRETCHY_TRUE | OpAttrs::SYMMETRIC_TRUE, + size: Some(Size::Scale3), + left: Some(MathSpacing::Zero), + right: Some(MathSpacing::Zero), + }), + "/" ); } diff --git a/crates/mathml-renderer/src/attribute.rs b/crates/mathml-renderer/src/attribute.rs index 5765f0b6..cf72f6ce 100644 --- a/crates/mathml-renderer/src/attribute.rs +++ b/crates/mathml-renderer/src/attribute.rs @@ -4,16 +4,6 @@ use serde::Serialize; use strum_macros::IntoStaticStr; -/// mathvariant attribute -#[derive(Debug, Clone, Copy, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize))] -pub enum MathVariant { - /// This is enforced by setting `mathvariant="normal"`. - Normal, - /// This is enforced by transforming the characters themselves. - Transform(TextTransform), -} - bitflags! { #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -24,7 +14,7 @@ bitflags! { const NO_MOVABLE_LIMITS = 1 << 2; const FORCE_MOVABLE_LIMITS = 1 << 3; const FORM_PREFIX = 1 << 4; - // const FORM_INFIX = 1 << 5; + const FORM_INFIX = 1 << 5; const FORM_POSTFIX = 1 << 6; const SYMMETRIC_TRUE = 1 << 7; } @@ -60,6 +50,9 @@ impl OpAttrs { if self.contains(OpAttrs::FORM_PREFIX) { s.push_str(r#" form="prefix""#); } + if self.contains(OpAttrs::FORM_INFIX) { + s.push_str(r#" form="infix""#); + } if self.contains(OpAttrs::FORM_POSTFIX) { s.push_str(r#" form="postfix""#); } @@ -80,7 +73,7 @@ pub enum LetterAttr { #[cfg_attr(feature = "serde", derive(Serialize))] pub enum Size { #[strum(serialize = "1.2em")] - Scale1, + Scale1 = 1, #[strum(serialize = "1.623em")] Scale2, #[strum(serialize = "2.047em")] @@ -89,15 +82,6 @@ pub enum Size { Scale4, } -#[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)] -#[cfg_attr(feature = "serde", derive(Serialize))] -pub enum ParenType { - #[strum(serialize = r#" form="prefix""#)] - Open = 1, - #[strum(serialize = r#" form="postfix""#)] - Close, -} - /// display style #[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)] #[cfg_attr(feature = "serde", derive(Serialize))] @@ -362,7 +346,7 @@ impl TextTransform { #[cfg(test)] mod tests { - use super::{MathVariant, TextTransform}; + use super::TextTransform; #[test] fn transform_test() { @@ -401,16 +385,4 @@ mod tests { ); } } - - #[test] - fn size_test() { - assert_eq!( - std::mem::size_of::(), - std::mem::size_of::() - ); - assert_eq!( - std::mem::size_of::>(), - std::mem::size_of::() - ); - } } diff --git a/crates/mathml-renderer/src/lib.rs b/crates/mathml-renderer/src/lib.rs index 5edc09ce..27e93872 100644 --- a/crates/mathml-renderer/src/lib.rs +++ b/crates/mathml-renderer/src/lib.rs @@ -17,6 +17,7 @@ //! attrs: OpAttrs::empty(), //! left: Some(MathSpacing::Zero), //! right: None, +//! size: None, //! }, //! symbol: &Node::IdentifierChar('i', LetterAttr::Default), //! }, diff --git a/crates/mathml-renderer/src/symbol.rs b/crates/mathml-renderer/src/symbol.rs index 111f5f10..8fcd9c55 100644 --- a/crates/mathml-renderer/src/symbol.rs +++ b/crates/mathml-renderer/src/symbol.rs @@ -135,10 +135,10 @@ impl OrdLike { let (stretchy, spacing) = match self.cat { OrdCategory::F | OrdCategory::G => (Stretchy::Always, DelimiterSpacing::Zero), OrdCategory::FGandForceDefault => { - (Stretchy::PrePostfix, DelimiterSpacing::InfixNonZero) + (Stretchy::PrePostfix, DelimiterSpacing::InfixRelation) } OrdCategory::K => (Stretchy::Never, DelimiterSpacing::Zero), - OrdCategory::KButUsedToBeB => (Stretchy::Never, DelimiterSpacing::NonZero), + OrdCategory::KButUsedToBeB => (Stretchy::Never, DelimiterSpacing::Other), OrdCategory::D | OrdCategory::E | OrdCategory::I | OrdCategory::IK => { return None; } @@ -200,7 +200,7 @@ impl Rel { RelCategory::A => Some(StretchableOp { char: self.char, stretchy: Stretchy::AlwaysAsymmetric, - spacing: DelimiterSpacing::NonZero, + spacing: DelimiterSpacing::Relation, }), RelCategory::Default => None, } @@ -236,11 +236,13 @@ pub enum Stretchy { pub enum DelimiterSpacing { /// Never has any spacing, even when used as an infix operator (e.g. `(`, `)`). Zero, - /// Has spacing when used as an infix operator, but not when used as a prefix or postfix - /// operator (e.g. `|`). - InfixNonZero, - /// Always has spacing, even when used as a prefix or postfix operator (e.g. `/`). - NonZero, + /// Has relation spacing when used as an infix operator, but not when used as a prefix or + /// postfix operator (e.g. `|`). + InfixRelation, + /// Always has relation spacing, even when used as a prefix or postfix operator (e.g. `↑`). + Relation, + /// Always has some spacing, even when used as a prefix or postfix operator (e.g. `/`). + Other, } #[derive(Debug, Clone, PartialEq, Eq, Copy)]