1use std::path::PathBuf;
2
3use flams_ftml::{FTML_CONTENT, FtmlResult};
4use flams_math_archives::{
5 MathArchive,
6 artifacts::{ContentResult, ContentUpdate, FileOrString, FtmlString},
7 backend::{AnyBackend, GlobalBackend, LocalBackend},
8 utils::{AllSyncEngine, path_ext::PathExt},
9};
10use flams_stex::RusTeX;
11use ftml_solver::CHECK;
12use ftml_uris::{ArchiveId, DocumentUri};
13
14pub fn check(archive: ArchiveId, path: PathBuf, persist: bool, truncate: bool) {
15 let _ = enable_ansi_support::enable_ansi_support();
16 tracing_subscriber::fmt()
17 .with_max_level(tracing::Level::INFO)
18 .init();
19 GlobalBackend::initialize::<AllSyncEngine>(false);
20 let (uri, full_path) = GlobalBackend
21 .get()
22 .with_local_archive(&archive, |a| {
23 a.map(|a| (a.uri().clone(), a.source_dir().join(&path)))
24 })
25 .expect("File not found in archive");
26 let uri =
27 DocumentUri::from_archive_relpath(uri, &path.as_slash_str()).expect("Invalid file path");
28 let text = std::fs::read_to_string(&full_path).expect("error reading tex file");
29 let mh = flams_math_archives::mathhub::mathhubs()
30 .iter()
31 .copied()
32 .map(|p| p.display().to_string())
33 .collect::<Vec<_>>()
34 .join(",");
35
36 tracing::info!("Initializing RusTeX...");
37 RusTeX::initialize();
38
39 tracing::info!("Running RusTeX...");
40 let rustex = RusTeX::get()
41 .expect("Failed to initialize RusTeX")
42 .builder()
43 .set_envs([
44 ("STEX_USESMS".to_string(), "true".to_string()),
45 ("MATHHUB".to_string(), mh),
46 ])
47 .set_sourcerefs(true)
48 .set_font_debug_info(true)
49 .set_string(&full_path, &text)
50 .expect("Failed to initialize RusTeX"); let (res, _) = rustex.run();
53 if let Some(e) = &res.error {
54 panic!("{e:?}");
55 }
56 tracing::info!("RusTeX: success");
57 let html = res.to_string();
58 if persist
59 && let Err(e) = GlobalBackend.get().save(
60 &uri,
61 None,
62 FileOrString::Str("".into()),
63 flams_stex::RUSTEX.id(),
64 Some(Box::new(FtmlString(html.clone().into_boxed_str()))),
65 )
66 {
67 panic!("Error persisting: {e}")
68 }
69 let r: FtmlResult = match flams_system::logging::ignore_traces(|| {
70 flams_ftml::build_ftml(&AnyBackend::Global, &html, uri.clone())
71 }) {
72 Ok(r) => r,
73 Err(e) => panic!("Error: {e}"),
74 };
75 if !r.errors.is_empty() {
76 for e in r.errors {
77 tracing::error!("Error {e}");
78 }
79 panic!("FTML extraction failed");
80 }
81 tracing::info!("Extracting FTML: success");
82 let doc = r.doc.document.clone();
83 let modules = r.doc.modules.clone();
84 if persist
85 && let Err(e) = GlobalBackend.get().save(
86 &uri,
87 None,
88 FileOrString::Str("".into()),
89 FTML_CONTENT.id(),
90 Some(Box::new(ContentResult {
91 document: r.doc.document,
92 modules: r.doc.modules,
93 data: r.doc.data,
94 body: r.body,
95 inner_offset: r.inner_offset,
96 css: r.css,
97 ftml: r.ftml,
98 triples: r.doc.triples,
99 })),
100 )
101 {
102 panic!("Error persisting: {e}")
103 }
104 let mut checker =
105 ftml_solver::Checker::<ftml_solver::split::SingleThreadedSplit>::new(AnyBackend::Global);
106
107 let _ = checker.add_modules(modules);
108 let (mut drs, modules) = match checker.check_document(&doc) {
109 Ok((drs, modules)) => (drs, modules),
110 Err(e) => {
111 panic!("Error checking: Missing module: {e}");
112 }
113 };
114 if persist
115 && let Err(e) = GlobalBackend.get().save(
116 &uri,
117 None,
118 FileOrString::Str("".into()),
119 CHECK.id(),
120 Some(Box::new(ContentUpdate {
121 document: Some(doc),
122 modules,
123 })),
124 )
125 {
126 panic!("Error persisting: {e}")
127 }
128 if truncate {
129 drs.filter_failures(false);
130 }
131 println!("{}", drs.colored());
132}