From dde65d2aaaa41f26d32a6c7152a8fbdd1effb3a9 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Tue, 10 Jun 2025 17:29:46 +0100 Subject: [PATCH] Extract element utility fns to `element_util.rs` Makes `interface.rs` file easier to navigate. Also extracted `enable_logs` to `logs.rs`. This is a refactoring that I've extracted from #374, where these functions are used by both the stateful and the stateless interface and I wanted to avoid any dependencies from `stateless_interface` on `interface`. --- src/canonicalize.rs | 6 +- src/chemistry.rs | 2 +- src/element_util.rs | 326 ++++++++++++++++++++++++++++++++++++++ src/infer_intent.rs | 2 +- src/interface.rs | 349 +---------------------------------------- src/lib.rs | 4 +- src/logs.rs | 25 +++ src/navigate.rs | 3 +- src/xpath_functions.rs | 4 +- tests/common/mod.rs | 1 + 10 files changed, 367 insertions(+), 355 deletions(-) create mode 100644 src/element_util.rs create mode 100644 src/logs.rs diff --git a/src/canonicalize.rs b/src/canonicalize.rs index c7117868..10fcc51f 100644 --- a/src/canonicalize.rs +++ b/src/canonicalize.rs @@ -4392,7 +4392,7 @@ mod canonicalize_tests { #[test] fn illegal_mathml_element() { - use crate::interface::*; + use crate::element_util::{get_element, trim_element}; let test_str = "f"; let package1 = &parser::parse(test_str).expect("Failed to parse test input"); let mathml = get_element(package1); @@ -4495,7 +4495,7 @@ mod canonicalize_tests { #[test] fn mrow_with_intent_and_single_child() { - use crate::interface::*; + use crate::element_util::{get_element, trim_element}; use sxd_document::parser; use crate::canonicalize::canonicalize; // this forces initialization @@ -4519,7 +4519,7 @@ mod canonicalize_tests { #[test] fn empty_mrow_with_intent() { // we don't want to remove the mrow because the intent on the mi would reference itself - use crate::interface::*; + use crate::element_util::{get_element, trim_element}; use sxd_document::parser; use crate::canonicalize::canonicalize; // this forces initialization diff --git a/src/chemistry.rs b/src/chemistry.rs index 503f5013..b582b405 100644 --- a/src/chemistry.rs +++ b/src/chemistry.rs @@ -1818,7 +1818,7 @@ mod chem_tests { fn parse_mathml_string(test: &str, test_mathml: F) -> bool where F: Fn(Element) -> bool { use sxd_document::parser; - use crate::interface::{get_element, trim_element}; + use crate::element_util::{get_element, trim_element}; let new_package = parser::parse(&test); if let Err(e) = new_package { diff --git a/src/element_util.rs b/src/element_util.rs new file mode 100644 index 00000000..e0c7c4f8 --- /dev/null +++ b/src/element_util.rs @@ -0,0 +1,326 @@ +use crate::canonicalize::{as_element, name}; +use crate::errors::*; +use crate::logs::enable_logs; +use crate::xpath_functions::{is_leaf, IsNode}; +use lazy_static::lazy_static; +use regex::Regex; +use sxd_document::{Package}; +use sxd_document::dom::*; + +pub fn get_element(package: &Package) -> Element { + enable_logs(); + let doc = package.as_document(); + let mut result = None; + for root_child in doc.root().children() { + if let ChildOfRoot::Element(e) = root_child { + assert!(result.is_none()); + result = Some(e); + } + } + return result.unwrap(); +} + +/// returns Ok() if two Documents are equal or some info where they differ in the Err +// Not really meant to be public -- used by tests in some packages +#[allow(dead_code)] +pub fn is_same_element(e1: Element, e2: Element) -> Result<()> { + enable_logs(); + if name(e1) != name(e2) { + bail!("Names not the same: {}, {}", name(e1), name(e2)); + } + + // assume 'e' doesn't have element children until proven otherwise + // this means we keep Text children until we are proven they aren't needed + if e1.children().len() != e2.children().len() { + bail!( + "Children of {} have {} != {} children", + name(e1), + e1.children().len(), + e2.children().len() + ); + } + + if let Err(e) = attrs_are_same(e1.attributes(), e2.attributes()) { + bail!("In element {}, {}", name(e1), e); + } + + for (i, (c1, c2)) in e1.children().iter().zip(e2.children().iter()).enumerate() { + match c1 { + ChildOfElement::Element(child1) => { + if let ChildOfElement::Element(child2) = c2 { + is_same_element(*child1, *child2)?; + } else { + bail!("{} child #{}, first is element, second is something else", name(e1), i); + } + } + ChildOfElement::Comment(com1) => { + if let ChildOfElement::Comment(com2) = c2 { + if com1.text() != com2.text() { + bail!("{} child #{} -- comment text differs", name(e1), i); + } + } else { + bail!("{} child #{}, first is comment, second is something else", name(e1), i); + } + } + ChildOfElement::ProcessingInstruction(p1) => { + if let ChildOfElement::ProcessingInstruction(p2) = c2 { + if p1.target() != p2.target() || p1.value() != p2.value() { + bail!("{} child #{} -- processing instruction differs", name(e1), i); + } + } else { + bail!( + "{} child #{}, first is processing instruction, second is something else", + name(e1), + i + ); + } + } + ChildOfElement::Text(t1) => { + if let ChildOfElement::Text(t2) = c2 { + if t1.text() != t2.text() { + bail!("{} child #{} -- text differs", name(e1), i); + } + } else { + bail!("{} child #{}, first is text, second is something else", name(e1), i); + } + } + } + } + return Ok(()); + + /// compares attributes -- '==' didn't seems to work + fn attrs_are_same(attrs1: Vec, attrs2: Vec) -> Result<()> { + if attrs1.len() != attrs2.len() { + bail!("Attributes have different length: {:?} != {:?}", attrs1, attrs2); + } + // can't guarantee attrs are in the same order + for attr1 in attrs1 { + if let Some(found_attr2) = attrs2 + .iter() + .find(|&attr2| attr1.name().local_part() == attr2.name().local_part()) + { + if attr1.value() == found_attr2.value() { + continue; + } else { + bail!( + "Attribute named {} has differing values:\n '{}'\n '{}'", + attr1.name().local_part(), + attr1.value(), + found_attr2.value() + ); + } + } else { + bail!( + "Attribute name {} not in [{}]", + print_attr(&attr1), + print_attrs(&attrs2) + ); + } + } + return Ok(()); + + fn print_attr(attr: &Attribute) -> String { + return format!("@{}='{}'", attr.name().local_part(), attr.value()); + } + fn print_attrs(attrs: &[Attribute]) -> String { + return attrs.iter().map(print_attr).collect::>().join(", "); + } + } +} + +// used for testing trim +/// returns Ok() if two Documents are equal or some info where they differ in the Err +#[allow(dead_code)] +pub(crate) fn is_same_doc(doc1: &Document, doc2: &Document) -> Result<()> { + // assume 'e' doesn't have element children until proven otherwise + // this means we keep Text children until we are proven they aren't needed + if doc1.root().children().len() != doc2.root().children().len() { + bail!( + "Children of docs have {} != {} children", + doc1.root().children().len(), + doc2.root().children().len() + ); + } + + for (i, (c1, c2)) in doc1 + .root() + .children() + .iter() + .zip(doc2.root().children().iter()) + .enumerate() + { + match c1 { + ChildOfRoot::Element(e1) => { + if let ChildOfRoot::Element(e2) = c2 { + is_same_element(*e1, *e2)?; + } else { + bail!("child #{}, first is element, second is something else", i); + } + } + ChildOfRoot::Comment(com1) => { + if let ChildOfRoot::Comment(com2) = c2 { + if com1.text() != com2.text() { + bail!("child #{} -- comment text differs", i); + } + } else { + bail!("child #{}, first is comment, second is something else", i); + } + } + ChildOfRoot::ProcessingInstruction(p1) => { + if let ChildOfRoot::ProcessingInstruction(p2) = c2 { + if p1.target() != p2.target() || p1.value() != p2.value() { + bail!("child #{} -- processing instruction differs", i); + } + } else { + bail!( + "child #{}, first is processing instruction, second is something else", + i + ); + } + } + } + } + return Ok(()); +} + +/// Not really meant to be public -- used by tests in some packages +pub fn trim_element(e: Element, allow_structure_in_leaves: bool) { + // "this is text { + trim_element(c, allow_structure_in_leaves); + } + ChildOfElement::Text(t) => { + single_text += t.text(); + e.remove_child(child); + } + _ => { + e.remove_child(child); + } + } + } + + // CSS considers only space, tab, linefeed, and carriage return as collapsable whitespace + if !(is_leaf(e) || name(e) == "intent-literal" || single_text.is_empty()) { + // intent-literal comes from testing intent + // FIX: we have a problem -- what should happen??? + // FIX: For now, just keep the children and ignore the text and log an error -- shouldn't panic/crash + if !single_text.trim_matches(WHITESPACE).is_empty() { + error!( + "trim_element: both element and textual children which shouldn't happen -- ignoring text '{}'", + single_text + ); + } + return; + } + if e.children().is_empty() && !single_text.is_empty() { + // debug!("Combining text in {}: '{}' -> '{}'", e.name().local_part(), single_text, trimmed_text); + e.set_text(&WHITESPACE_MATCH.replace_all(&single_text, " ")); + } + + fn make_leaf_element(mathml_leaf: Element) { + // MathML leaves like really shouldn't have non-textual content, but you could have embedded HTML + // Here, we take convert them to leaves by grabbing up all the text and making that the content + // Potentially, we leave them and let (default) rules do something, but it makes other parts of the code + // messier because checking the text of a leaf becomes Option<&str> rather than just &str + let children = mathml_leaf.children(); + if children.is_empty() { + return; + } + + // gather up the text + let mut text = "".to_string(); + for child in children { + let child_text = match child { + ChildOfElement::Element(child) => { + if name(child) == "mglyph" { + child.attribute_value("alt").unwrap_or("").to_string() + } else { + gather_text(child) + } + } + ChildOfElement::Text(t) => { + // debug!("ChildOfElement::Text: '{}'", t.text()); + t.text().to_string() + } + _ => "".to_string(), + }; + if !child_text.is_empty() { + text += &child_text; + } + } + + // get rid of the old children and replace with the text we just built + mathml_leaf.clear_children(); + mathml_leaf.set_text(WHITESPACE_MATCH.replace_all(&text, " ").trim_matches(WHITESPACE)); + // debug!("make_leaf_element: text is '{}'", crate::canonicalize::as_text(mathml_leaf)); + + /// gather up all the contents of the element and return them with a leading space + fn gather_text(html: Element) -> String { + let mut text = "".to_string(); // since we are throwing out the element tag, add a space between the contents + for child in html.children() { + match child { + ChildOfElement::Element(child) => { + text += &gather_text(child); + } + ChildOfElement::Text(t) => text += t.text(), + _ => (), + } + } + // debug!("gather_text: '{}'", text); + return text; + } + } +} + +pub(crate) fn add_ids(mathml: Element) -> Element { + use std::time::SystemTime; + let time = if cfg!(target_family = "wasm") { + fastrand::usize(..) + } else { + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_millis() as usize + }; + let time_part = radix_fmt::radix(time, 36).to_string(); + let random_part = radix_fmt::radix(fastrand::u32(..), 36).to_string(); + let prefix = "M".to_string() + &time_part[time_part.len() - 3..] + &random_part[random_part.len() - 4..] + "-"; // begin with letter + add_ids_to_all(mathml, &prefix, 0); + return mathml; + + fn add_ids_to_all(mathml: Element, id_prefix: &str, count: usize) -> usize { + let mut count = count; + if mathml.attribute("id").is_none() { + mathml.set_attribute_value("id", (id_prefix.to_string() + &count.to_string()).as_str()); + mathml.set_attribute_value("data-id-added", "true"); + count += 1; + }; + + if crate::xpath_functions::is_leaf(mathml) { + return count; + } + + for child in mathml.children() { + let child = as_element(child); + count = add_ids_to_all(child, id_prefix, count); + } + return count; + } +} diff --git a/src/infer_intent.rs b/src/infer_intent.rs index 0248778e..e9526ad3 100644 --- a/src/infer_intent.rs +++ b/src/infer_intent.rs @@ -611,7 +611,7 @@ mod tests { fn test_intent(mathml: &str, target: &str, intent_error_recovery: &str) -> bool { - use crate::interface::*; + use crate::{interface::*, element_util::*}; // this forces initialization crate::interface::set_rules_dir(super::super::abs_rules_dir_path()).unwrap(); // crate::speech::SpeechRules::initialize_all_rules().unwrap(); diff --git a/src/interface.rs b/src/interface.rs index b9a99c40..f7bde19b 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -6,6 +6,7 @@ use std::cell::RefCell; use crate::canonicalize::{as_text, create_mathml_element}; use crate::errors::*; +use crate::logs::enable_logs; use phf::phf_map; use regex::{Captures, Regex}; use sxd_document::dom::*; @@ -13,36 +14,10 @@ use sxd_document::parser; use sxd_document::Package; use crate::canonicalize::{as_element, name}; - +use crate::element_util::*; use crate::navigate::*; use crate::pretty_print::mml_to_string; -use crate::xpath_functions::{is_leaf, IsNode}; - -#[cfg(feature = "enable-logs")] -use std::sync::Once; -#[cfg(feature = "enable-logs")] -static INIT: Once = Once::new(); - -fn enable_logs() { - #[cfg(feature = "enable-logs")] - INIT.call_once(||{ - #[cfg(target_os = "android")] - { - extern crate log; - extern crate android_logger; - - use log::*; - use android_logger::*; - - android_logger::init_once( - Config::default() - .with_max_level(LevelFilter::Trace) - .with_tag("MathCat") - ); - trace!("Activated Android logger!"); - } - }); -} +use crate::xpath_functions::is_leaf; // wrap up some common functionality between the call from 'main' and AT fn cleanup_mathml(mathml: Element) -> Result { @@ -540,55 +515,6 @@ pub fn errors_to_string(e: &Error) -> String { return result; } -fn add_ids(mathml: Element) -> Element { - use std::time::SystemTime; - let time = if cfg!(target_family = "wasm") { - fastrand::usize(..) - } else { - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_millis() as usize - }; - let time_part = radix_fmt::radix(time, 36).to_string(); - let random_part = radix_fmt::radix(fastrand::u32(..), 36).to_string(); - let prefix = "M".to_string() + &time_part[time_part.len() - 3..] + &random_part[random_part.len() - 4..] + "-"; // begin with letter - add_ids_to_all(mathml, &prefix, 0); - return mathml; - - fn add_ids_to_all(mathml: Element, id_prefix: &str, count: usize) -> usize { - let mut count = count; - if mathml.attribute("id").is_none() { - mathml.set_attribute_value("id", (id_prefix.to_string() + &count.to_string()).as_str()); - mathml.set_attribute_value("data-id-added", "true"); - count += 1; - }; - - if crate::xpath_functions::is_leaf(mathml) { - return count; - } - - for child in mathml.children() { - let child = as_element(child); - count = add_ids_to_all(child, id_prefix, count); - } - return count; - } -} - -pub fn get_element(package: &Package) -> Element { - enable_logs(); - let doc = package.as_document(); - let mut result = None; - for root_child in doc.root().children() { - if let ChildOfRoot::Element(e) = root_child { - assert!(result.is_none()); - result = Some(e); - } - } - return result.unwrap(); -} - /// Get the intent after setting the MathML /// Used in testing #[allow(dead_code)] @@ -609,275 +535,6 @@ fn trim_doc(doc: &Document) { } } -/// Not really meant to be public -- used by tests in some packages -pub fn trim_element(e: Element, allow_structure_in_leaves: bool) { - // "this is text { - trim_element(c, allow_structure_in_leaves); - } - ChildOfElement::Text(t) => { - single_text += t.text(); - e.remove_child(child); - } - _ => { - e.remove_child(child); - } - } - } - - // CSS considers only space, tab, linefeed, and carriage return as collapsable whitespace - if !(is_leaf(e) || name(e) == "intent-literal" || single_text.is_empty()) { - // intent-literal comes from testing intent - // FIX: we have a problem -- what should happen??? - // FIX: For now, just keep the children and ignore the text and log an error -- shouldn't panic/crash - if !single_text.trim_matches(WHITESPACE).is_empty() { - error!( - "trim_element: both element and textual children which shouldn't happen -- ignoring text '{}'", - single_text - ); - } - return; - } - if e.children().is_empty() && !single_text.is_empty() { - // debug!("Combining text in {}: '{}' -> '{}'", e.name().local_part(), single_text, trimmed_text); - e.set_text(&WHITESPACE_MATCH.replace_all(&single_text, " ")); - } - - fn make_leaf_element(mathml_leaf: Element) { - // MathML leaves like really shouldn't have non-textual content, but you could have embedded HTML - // Here, we take convert them to leaves by grabbing up all the text and making that the content - // Potentially, we leave them and let (default) rules do something, but it makes other parts of the code - // messier because checking the text of a leaf becomes Option<&str> rather than just &str - let children = mathml_leaf.children(); - if children.is_empty() { - return; - } - - // gather up the text - let mut text = "".to_string(); - for child in children { - let child_text = match child { - ChildOfElement::Element(child) => { - if name(child) == "mglyph" { - child.attribute_value("alt").unwrap_or("").to_string() - } else { - gather_text(child) - } - } - ChildOfElement::Text(t) => { - // debug!("ChildOfElement::Text: '{}'", t.text()); - t.text().to_string() - } - _ => "".to_string(), - }; - if !child_text.is_empty() { - text += &child_text; - } - } - - // get rid of the old children and replace with the text we just built - mathml_leaf.clear_children(); - mathml_leaf.set_text(WHITESPACE_MATCH.replace_all(&text, " ").trim_matches(WHITESPACE)); - // debug!("make_leaf_element: text is '{}'", crate::canonicalize::as_text(mathml_leaf)); - - /// gather up all the contents of the element and return them with a leading space - fn gather_text(html: Element) -> String { - let mut text = "".to_string(); // since we are throwing out the element tag, add a space between the contents - for child in html.children() { - match child { - ChildOfElement::Element(child) => { - text += &gather_text(child); - } - ChildOfElement::Text(t) => text += t.text(), - _ => (), - } - } - // debug!("gather_text: '{}'", text); - return text; - } - } -} - -// used for testing trim -/// returns Ok() if two Documents are equal or some info where they differ in the Err -#[allow(dead_code)] -fn is_same_doc(doc1: &Document, doc2: &Document) -> Result<()> { - // assume 'e' doesn't have element children until proven otherwise - // this means we keep Text children until we are proven they aren't needed - if doc1.root().children().len() != doc2.root().children().len() { - bail!( - "Children of docs have {} != {} children", - doc1.root().children().len(), - doc2.root().children().len() - ); - } - - for (i, (c1, c2)) in doc1 - .root() - .children() - .iter() - .zip(doc2.root().children().iter()) - .enumerate() - { - match c1 { - ChildOfRoot::Element(e1) => { - if let ChildOfRoot::Element(e2) = c2 { - is_same_element(*e1, *e2)?; - } else { - bail!("child #{}, first is element, second is something else", i); - } - } - ChildOfRoot::Comment(com1) => { - if let ChildOfRoot::Comment(com2) = c2 { - if com1.text() != com2.text() { - bail!("child #{} -- comment text differs", i); - } - } else { - bail!("child #{}, first is comment, second is something else", i); - } - } - ChildOfRoot::ProcessingInstruction(p1) => { - if let ChildOfRoot::ProcessingInstruction(p2) = c2 { - if p1.target() != p2.target() || p1.value() != p2.value() { - bail!("child #{} -- processing instruction differs", i); - } - } else { - bail!( - "child #{}, first is processing instruction, second is something else", - i - ); - } - } - } - } - return Ok(()); -} - -/// returns Ok() if two Documents are equal or some info where they differ in the Err -// Not really meant to be public -- used by tests in some packages -#[allow(dead_code)] -pub fn is_same_element(e1: Element, e2: Element) -> Result<()> { - enable_logs(); - if name(e1) != name(e2) { - bail!("Names not the same: {}, {}", name(e1), name(e2)); - } - - // assume 'e' doesn't have element children until proven otherwise - // this means we keep Text children until we are proven they aren't needed - if e1.children().len() != e2.children().len() { - bail!( - "Children of {} have {} != {} children", - name(e1), - e1.children().len(), - e2.children().len() - ); - } - - if let Err(e) = attrs_are_same(e1.attributes(), e2.attributes()) { - bail!("In element {}, {}", name(e1), e); - } - - for (i, (c1, c2)) in e1.children().iter().zip(e2.children().iter()).enumerate() { - match c1 { - ChildOfElement::Element(child1) => { - if let ChildOfElement::Element(child2) = c2 { - is_same_element(*child1, *child2)?; - } else { - bail!("{} child #{}, first is element, second is something else", name(e1), i); - } - } - ChildOfElement::Comment(com1) => { - if let ChildOfElement::Comment(com2) = c2 { - if com1.text() != com2.text() { - bail!("{} child #{} -- comment text differs", name(e1), i); - } - } else { - bail!("{} child #{}, first is comment, second is something else", name(e1), i); - } - } - ChildOfElement::ProcessingInstruction(p1) => { - if let ChildOfElement::ProcessingInstruction(p2) = c2 { - if p1.target() != p2.target() || p1.value() != p2.value() { - bail!("{} child #{} -- processing instruction differs", name(e1), i); - } - } else { - bail!( - "{} child #{}, first is processing instruction, second is something else", - name(e1), - i - ); - } - } - ChildOfElement::Text(t1) => { - if let ChildOfElement::Text(t2) = c2 { - if t1.text() != t2.text() { - bail!("{} child #{} -- text differs", name(e1), i); - } - } else { - bail!("{} child #{}, first is text, second is something else", name(e1), i); - } - } - } - } - return Ok(()); - - /// compares attributes -- '==' didn't seems to work - fn attrs_are_same(attrs1: Vec, attrs2: Vec) -> Result<()> { - if attrs1.len() != attrs2.len() { - bail!("Attributes have different length: {:?} != {:?}", attrs1, attrs2); - } - // can't guarantee attrs are in the same order - for attr1 in attrs1 { - if let Some(found_attr2) = attrs2 - .iter() - .find(|&attr2| attr1.name().local_part() == attr2.name().local_part()) - { - if attr1.value() == found_attr2.value() { - continue; - } else { - bail!( - "Attribute named {} has differing values:\n '{}'\n '{}'", - attr1.name().local_part(), - attr1.value(), - found_attr2.value() - ); - } - } else { - bail!( - "Attribute name {} not in [{}]", - print_attr(&attr1), - print_attrs(&attrs2) - ); - } - } - return Ok(()); - - fn print_attr(attr: &Attribute) -> String { - return format!("@{}='{}'", attr.name().local_part(), attr.value()); - } - fn print_attrs(attrs: &[Attribute]) -> String { - return attrs.iter().map(print_attr).collect::>().join(", "); - } - } -} - #[cfg(test)] mod tests { #[allow(unused_imports)] diff --git a/src/lib.rs b/src/lib.rs index 8ef01336..c62aa466 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,9 +50,11 @@ pub mod interface; pub use shim_filesystem::ZIPPED_RULE_FILES; mod canonicalize; +pub mod element_util; mod infer_intent; pub mod speech; mod braille; +mod logs; mod navigate; mod prefs; mod tts; @@ -90,7 +92,7 @@ pub fn abs_rules_dir_path() -> String { #[cfg(test)] pub fn are_strs_canonically_equal_with_locale(test: &str, target: &str, block_separators: &str, decimal_separators: &str) -> bool { - use crate::{interface::*, pretty_print::mml_to_string}; + use crate::{element_util::*, pretty_print::mml_to_string}; use sxd_document::parser; use crate::canonicalize::canonicalize; // this forces initialization diff --git a/src/logs.rs b/src/logs.rs new file mode 100644 index 00000000..da7aa8b8 --- /dev/null +++ b/src/logs.rs @@ -0,0 +1,25 @@ +#[cfg(feature = "enable-logs")] +use std::sync::Once; +#[cfg(feature = "enable-logs")] +static INIT: Once = Once::new(); + +pub(crate) fn enable_logs() { + #[cfg(feature = "enable-logs")] + INIT.call_once(||{ + #[cfg(target_os = "android")] + { + extern crate log; + extern crate android_logger; + + use log::*; + use android_logger::*; + + android_logger::init_once( + Config::default() + .with_max_level(LevelFilter::Trace) + .with_tag("MathCat") + ); + trace!("Activated Android logger!"); + } + }); +} diff --git a/src/navigate.rs b/src/navigate.rs index 5573737f..bd8fb0dc 100644 --- a/src/navigate.rs +++ b/src/navigate.rs @@ -921,6 +921,7 @@ mod tests { #[allow(unused_imports)] use crate::init_logger; use crate::interface::*; + use crate::element_util::*; #[cfg(test)] /// Assert if result_id != '' and it doesn't match the id of the result of the move @@ -2198,4 +2199,4 @@ mod tests { }); } } -} \ No newline at end of file +} diff --git a/src/xpath_functions.rs b/src/xpath_functions.rs index 185d2f75..444dea41 100644 --- a/src/xpath_functions.rs +++ b/src/xpath_functions.rs @@ -1449,7 +1449,7 @@ pub fn add_builtin_functions(context: &mut Context) { mod tests { use super::*; use sxd_document::parser; - use crate::interface::{trim_element, get_element}; + use crate::element_util::{trim_element, get_element}; fn init_word_list() { @@ -1639,4 +1639,4 @@ mod tests { let mn = as_element(as_element(fraction.children()[1]).children()[0]); assert_eq!(EdgeNode::edge_node(mn, true, "2D"), None); } -} \ No newline at end of file +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs index d35fc0ab..29cd6a12 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -5,6 +5,7 @@ use regex::Regex; extern crate lazy_static; use lazy_static::lazy_static; pub use libmathcat::interface::*; +use libmathcat::element_util::*; #[allow(dead_code)] pub fn init_logger() {