diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a3b1b1c6f8..6c0658d68e 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -266,6 +266,7 @@ Yuuki Gabriele Patriarca SecretX Daniel Pechersky fernandolins <1887601+fernandolins@users.noreply.github.com> +Athitheya Gobinathan ******************** diff --git a/rslib/src/cloze.rs b/rslib/src/cloze.rs index 70a5d1703a..ab6f2dfc99 100644 --- a/rslib/src/cloze.rs +++ b/rslib/src/cloze.rs @@ -91,16 +91,44 @@ fn tokenize(mut text: &str) -> impl Iterator> { nom::error::ErrorKind::Eof, ))); } - let mut other_token = alt((open_cloze, close_cloze)); - // start with the no-match case let mut index = text.len(); - for (idx, _) in text.char_indices() { - if other_token.parse(&text[idx..]).is_ok() { - index = idx; + let mut i = 0; + let mut mathjax_end: Option<&str> = None; + while i < text.len() { + let rest = &text[i..]; + // Cloze openings should be recognized everywhere, including inside MathJax. + if open_cloze(rest).is_ok() { + index = i; break; } + // Cloze closings should only be recognized outside MathJax. + if mathjax_end.is_none() && close_cloze(rest).is_ok() { + index = i; + break; + } + // Enter MathJax when not already inside it. + if mathjax_end.is_none() { + if rest.starts_with(r"\(") { + mathjax_end = Some(r"\)"); + i += 2; + continue; + } + if rest.starts_with(r"\[") { + mathjax_end = Some(r"\]"); + i += 2; + continue; + } + } else if let Some(end) = mathjax_end { + // Exit MathJax when we hit the matching delimiter. + if rest.starts_with(end) { + mathjax_end = None; + i += 2; + continue; + } + } + i += rest.chars().next().unwrap().len_utf8(); } - Ok((&text[index..], Token::Text(&text[0..index]))) + Ok((&text[index..], Token::Text(&text[..index]))) } std::iter::from_fn(move || { @@ -665,6 +693,19 @@ mod test { ); } + #[test] + fn cloze_with_mathjax_braces() { + let text = r"{{c1:: \( \frac{1}{\sqrt{\pi}} \) }}"; + assert_eq!( + strip_html(reveal_cloze_text(text, 1, true).as_ref()), + "[...]" + ); + assert_eq!( + strip_html(reveal_cloze_text(text, 1, false).as_ref()), + r" \( \frac{1}{\sqrt{\pi}} \) " + ); + } + #[test] fn non_latin() { assert!(cloze_numbers_in_string("öaöaöööaö").is_empty());