1pub mod arena;
2pub mod color;
3#[macro_use]
4pub mod error;
5pub mod cleaners;
6pub mod def_parser;
7pub mod dimension;
8pub mod float;
9pub mod font;
10pub mod glue;
11pub mod ligature;
12pub mod local_assignments;
13pub mod locator;
14pub mod mathchar;
15pub mod model;
16pub mod mudimension;
17pub mod muglue;
18pub mod number;
19pub mod numeric_ops;
20pub mod object;
21pub mod pair;
22pub mod relaxng;
23pub mod store;
24pub mod xml;
25
26use std::rc::Rc;
27
28use crate::{common::error::*, fmt};
29
30#[derive(Clone, Debug)]
31pub enum InputFormat {
32 TeX,
33 Bib,
34}
35#[derive(Clone, Debug)]
36pub enum OutputFormat {
37 TeX,
38 Box,
39 XML,
40 HTML5,
41 XHTML,
42}
43#[derive(Clone, Debug)]
44pub enum DataSize {
45 Math,
46 Fragment,
47 Document,
48 Archive,
49}
50
51#[derive(Clone, Debug)]
52pub enum DigestionMode {
53 TeX,
54 LaTeX,
55 AmSTeX,
56 BibTeX,
57}
58impl fmt::Display for DigestionMode {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 use self::DigestionMode::*;
61 let formatted = match *self {
62 TeX => "TeX",
63 LaTeX => "LaTeX",
64 AmSTeX => "AmSTeX",
65 BibTeX => "BibTeX",
66 };
67 write!(f, "{formatted}")
68 }
69}
70
71impl DigestionMode {
72 pub fn extension(&self) -> String {
73 match *self {
74 DigestionMode::TeX | DigestionMode::LaTeX | DigestionMode::AmSTeX => "tex",
75 DigestionMode::BibTeX => "bib",
76 }
77 .to_string()
78 }
79}
80
81pub type BindingDispatcher = Rc<dyn Fn(&str) -> Option<Result<()>>>;
87
88pub type BindingSource = Option<String>;
94
95pub type ResolvingBindingDispatcher = Rc<dyn Fn(&str) -> Option<Result<BindingSource>>>;
101
102pub fn native_dispatcher(
107 f: impl Fn(&str) -> Option<Result<()>> + 'static,
108) -> ResolvingBindingDispatcher {
109 Rc::new(move |request| f(request).map(|r| r.map(|()| None)))
110}
111
112pub type LabelMappingHook = Rc<dyn Fn(&str, &str, bool) -> (Option<String>, Option<String>)>;
115
116#[derive(Clone)]
117pub struct Config {
118 pub verbosity: i32,
119 pub format: OutputFormat,
120 pub whatsin: DataSize,
121 pub whatsout: DataSize,
122 pub preamble: Option<String>,
123 pub postamble: Option<String>,
124 pub mode: Option<DigestionMode>,
125 pub bindings_dispatch: Option<BindingDispatcher>,
126 pub extra_bindings_dispatch: Option<BindingDispatcher>,
127 pub preload: Option<Vec<String>>,
129 pub search_paths: Option<Vec<String>>,
131 pub include_comments: Option<bool>,
133 pub strict: Option<bool>,
135 pub include_styles: Option<bool>,
139 pub nomathparse: Option<bool>,
141 pub source_map: Option<bool>,
145 pub inputencoding: Option<String>,
151 pub streaming: Option<usize>,
160}
161impl Default for Config {
162 fn default() -> Self {
163 Config {
164 verbosity: 1,
165 format: OutputFormat::XML,
166 whatsin: DataSize::Document,
167 whatsout: DataSize::Document,
168 preamble: None,
169 postamble: None,
170 mode: Some(DigestionMode::LaTeX),
171 bindings_dispatch: None,
172 extra_bindings_dispatch: None,
173 preload: None,
174 search_paths: None,
175 include_comments: None,
176 strict: None,
177 include_styles: None,
178 nomathparse: None,
179 source_map: None,
180 inputencoding: None,
181 streaming: None,
182 }
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[test]
191 fn digestion_mode_display() {
192 assert_eq!(format!("{}", DigestionMode::TeX), "TeX");
193 assert_eq!(format!("{}", DigestionMode::LaTeX), "LaTeX");
194 assert_eq!(format!("{}", DigestionMode::AmSTeX), "AmSTeX");
195 assert_eq!(format!("{}", DigestionMode::BibTeX), "BibTeX");
196 }
197
198 #[test]
199 fn digestion_mode_extension() {
200 assert_eq!(DigestionMode::TeX.extension(), "tex");
201 assert_eq!(DigestionMode::LaTeX.extension(), "tex");
202 assert_eq!(DigestionMode::AmSTeX.extension(), "tex");
203 assert_eq!(DigestionMode::BibTeX.extension(), "bib");
204 }
205
206 #[test]
207 fn config_default_fields() {
208 let c = Config::default();
209 assert_eq!(c.verbosity, 1);
210 assert!(matches!(c.format, OutputFormat::XML));
211 assert!(matches!(c.whatsin, DataSize::Document));
212 assert!(matches!(c.whatsout, DataSize::Document));
213 assert!(c.preamble.is_none());
214 assert!(c.postamble.is_none());
215 assert!(matches!(c.mode, Some(DigestionMode::LaTeX)));
216 assert!(c.bindings_dispatch.is_none());
217 assert!(c.extra_bindings_dispatch.is_none());
218 assert!(c.preload.is_none());
219 assert!(c.search_paths.is_none());
220 assert!(c.include_comments.is_none());
221 assert!(c.nomathparse.is_none());
222 assert!(c.source_map.is_none());
223 }
224
225 #[test]
226 fn config_clone_preserves_fields() {
227 let c = Config {
228 verbosity: 5,
229 preload: Some(vec!["ar5iv.sty".to_string()]),
230 ..Default::default()
231 };
232 let c2 = c.clone();
233 assert_eq!(c2.verbosity, 5);
234 assert_eq!(c2.preload.as_ref().unwrap(), &vec!["ar5iv.sty".to_string()]);
235 }
236
237 #[test]
238 fn input_format_variants() {
239 let _ = InputFormat::TeX;
241 let _ = InputFormat::Bib;
242 let cloned = InputFormat::TeX.clone();
243 assert!(matches!(cloned, InputFormat::TeX));
244 }
245
246 #[test]
247 fn output_format_variants() {
248 let _ = OutputFormat::TeX;
249 let _ = OutputFormat::Box;
250 let _ = OutputFormat::XML;
251 let _ = OutputFormat::HTML5;
252 let _ = OutputFormat::XHTML;
253 let cloned = OutputFormat::XML.clone();
254 assert!(matches!(cloned, OutputFormat::XML));
255 }
256
257 #[test]
258 fn data_size_variants() {
259 let _ = DataSize::Math;
260 let _ = DataSize::Fragment;
261 let _ = DataSize::Document;
262 let _ = DataSize::Archive;
263 let cloned = DataSize::Document.clone();
264 assert!(matches!(cloned, DataSize::Document));
265 }
266}