mathquill_js/
lib.rs

1#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
2#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/loading.md"))]
3//!
4//! ## API Structure
5//! Read the docs on the [MathQuill](crate::MathQuill) struct, everything starts from there.
6//!
7//! ## Contrived example
8//! From their docs:
9//! ```js
10//! var answerSpan = document.getElementById('answer');
11//! var answerMathField = MQ.MathField(answerSpan, {
12//!   handlers: {
13//!     edit: function() {
14//!       var enteredMath = answerMathField.latex(); // Get entered math in LaTeX format
15//!       checkAnswer(enteredMath);
16//!     }
17//!   }
18//! });
19//! ```
20//! This would translate to something like:
21//! ```rust
22#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/examples/field.rs"))]
23//! ```
24//!
25//! If you don't want the field to be editable, you can use a static field
26//! and manually set the latext content to be whatever you want, like this:
27//! ```rust
28#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/examples/static.rs"))]
29//! ```
30//!
31//! See the examples directory for more information
32
33#[allow(unused_imports)]
34use tracing::{debug, error, info, trace, warn};
35
36use web_sys::wasm_bindgen::prelude::Closure;
37
38/// The primary interface to the MathQuill library.
39pub struct MathQuill(mathquill_js_sys::MathQuill);
40
41impl MathQuill {
42  /// JS errors if the MathQuill library is not loaded already.
43  ///
44  /// Will reference a global stored in the mathquill library,
45  /// so you can call this as many times as you want and assume
46  /// each instance is the same as the last:
47  /// `By default, MathQuill overwrites the global MathQuill variable when loaded`,
48  /// copied from <https://docs.mathquill.com/en/latest/Api_Methods/#api-methods>
49  pub fn get_global_interface() -> Self {
50    Self(mathquill_js_sys::MathQuill::getInterface(2))
51  }
52
53  /// When config.handlers is dropped, the mounted field's callbacks will be invalidated
54  pub fn mount_field(
55    &self,
56    html_element: &web_sys::HtmlElement,
57    config: &Config<MathField>,
58  ) -> MathField {
59    debug!(el = ?html_element, "Mounting a (mutable) field");
60    MathField(self.0.MathField(html_element, config.0.get_js_value()))
61  }
62
63  pub fn mount_static_field(&self, html_element: &web_sys::HtmlElement) -> StaticMath {
64    debug!(el = ?html_element, "Mounting a static field");
65    StaticMath(self.0.StaticMath(html_element))
66  }
67
68  pub fn get_field(&self, el: &web_sys::HtmlElement) -> Option<MathField> {
69    self.0.get_field(el).map(MathField)
70  }
71
72  pub fn get_static_field(&self, el: &web_sys::HtmlElement) -> Option<StaticMath> {
73    self.0.get_static_field(el).map(StaticMath)
74  }
75}
76
77/// Read docs on [mathquill_js_sys::Config] about manual memory management
78pub struct Config<MathField>(mathquill_js_sys::Config<<MathField as IntoInner>::Inner>)
79where
80  MathField: IntoInner;
81
82impl<T> Default for Config<T>
83where
84  T: IntoInner,
85{
86  fn default() -> Self {
87    Self(mathquill_js_sys::Config::default())
88  }
89}
90
91pub struct HandlersMut<'config, MathField>(
92  &'config mut mathquill_js_sys::Handlers<<MathField as IntoInner>::Inner>,
93)
94where
95  MathField: IntoInner;
96impl<T> Config<T>
97where
98  T: IntoInner,
99{
100  pub fn handlers(&mut self) -> HandlersMut<'_, T> {
101    HandlersMut(&mut self.0.handlers)
102  }
103}
104impl<'config> HandlersMut<'config, MathField> {
105  pub fn on_edit_field(&mut self, callback: impl FnMut() + 'static) {
106    self.0.edit = Some(Closure::new(callback));
107  }
108}
109
110/// Wrapper around [mathquill_js_sys::MathField]
111pub struct MathField(mathquill_js_sys::MathField);
112
113/// Used internally, exposed for correctness in case
114/// you are also using [mathquill_js_sys]
115pub trait IntoInner {
116  type Inner;
117}
118
119impl IntoInner for MathField {
120  type Inner = mathquill_js_sys::MathField;
121}
122
123impl MathField {
124  pub fn latex(&self) -> String {
125    self.0.latex()
126  }
127
128  pub fn set_latex(&self, latex: &str) {
129    self.0.set_latex(latex);
130  }
131}
132
133/// Wrapper around [mathquill_js_sys::StaticMath]
134pub struct StaticMath(mathquill_js_sys::StaticMath);
135
136impl IntoInner for StaticMath {
137  type Inner = mathquill_js_sys::StaticMath;
138}
139
140impl StaticMath {
141  pub fn latex(&self) -> String {
142    self.0.latex()
143  }
144
145  pub fn set_latex(&self, latex: &str) {
146    self.0.set_latex(latex);
147  }
148}