1use flams_ontology::{narration::documents::DocumentStyles, uris::NarrativeURI, Unchecked};
2use flams_utils::{id_counters::IdCounter, vecmap::VecSet};
3use ftml_extraction::prelude::{Attributes, FTMLExtractor, GnoteState};
4use leptos::{prelude::expect_context, web_sys::Element};
5use smallvec::SmallVec;
6use std::borrow::Cow;
7
8#[derive(Default)]
9pub struct DOMExtractor {
10 in_notation: bool,
11 in_term: bool,
12 pub(crate) styles: DocumentStyles,
13 id_counter: IdCounter,
14}
15
16impl FTMLExtractor for DOMExtractor {
17 type Attr<'a> = NodeAttrs<'a>;
18
19 #[inline(always)]
20 fn add_error(&mut self, err: ftml_extraction::errors::FTMLError) {
21 tracing::error!("{err}");
22 }
23
24 fn styles(&mut self) -> &mut DocumentStyles {
25 &mut self.styles
26 }
27
28 #[inline]
29 fn new_id(&mut self, prefix: Cow<'static, str>) -> Box<str> {
30 self.id_counter.new_id(prefix)
31 }
32
33 #[inline]
34 fn in_term(&self) -> bool {
35 self.in_term
36 }
37
38 #[inline]
39 fn set_in_term(&mut self, value: bool) {
40 self.in_term = value
41 }
42
43 #[inline]
44 fn in_notation(&self) -> bool {
45 self.in_notation
46 }
47
48 #[cfg(feature = "rdf")]
49 const RDF: bool = false;
50
51 #[cfg(feature = "rdf")]
52 fn add_triples<const N: usize>(&mut self, _triples: [flams_ontology::rdf::Triple; N]) {}
53
54 #[cfg(feature = "rdf")]
55 fn get_content_iri(&self) -> Option<flams_ontology::rdf::NamedNode> {
56 todo!()
57 }
58 #[cfg(feature = "rdf")]
59 fn get_document_iri(&self) -> flams_ontology::rdf::NamedNode {
60 todo!()
61 }
62
63 fn add_objective(
64 &mut self,
65 _uri: flams_ontology::uris::SymbolURI,
66 _dim: flams_ontology::narration::problems::CognitiveDimension,
67 ) {
68 todo!()
69 }
70 fn add_precondition(
71 &mut self,
72 _uri: flams_ontology::uris::SymbolURI,
73 _dim: flams_ontology::narration::problems::CognitiveDimension,
74 ) {
75 todo!()
76 }
77
78 fn resolve_variable_name(
79 &self,
80 _name: flams_ontology::uris::Name,
81 ) -> flams_ontology::content::terms::Var {
82 todo!()
83 }
84
85 fn add_arg(
86 &mut self,
87 _pos: (u8, Option<u8>),
88 _tm: flams_ontology::content::terms::Term,
89 _mode: flams_ontology::content::terms::ArgMode,
90 ) -> Result<(), ()> {
91 todo!()
92 }
93 fn add_content_element(
94 &mut self,
95 _elem: flams_ontology::content::declarations::OpenDeclaration<Unchecked>,
96 ) -> Result<(), flams_ontology::content::declarations::OpenDeclaration<Unchecked>> {
97 todo!()
98 }
99 fn add_document_element(
100 &mut self,
101 _elem: flams_ontology::narration::DocumentElement<Unchecked>,
102 ) {
103 todo!()
104 }
105 fn add_module(&mut self, _module: flams_ontology::content::modules::OpenModule<Unchecked>) {
106 todo!()
107 }
108 fn add_notation(
109 &mut self,
110 _spec: ftml_extraction::prelude::NotationSpec,
111 ) -> Result<(), ftml_extraction::prelude::NotationSpec> {
112 todo!()
113 }
114 fn add_op_notation(
115 &mut self,
116 _op: flams_ontology::narration::notations::OpNotation,
117 ) -> Result<(), flams_ontology::narration::notations::OpNotation> {
118 todo!()
119 }
120 fn add_resource<T: flams_ontology::Resourcable>(
121 &mut self,
122 _t: &T,
123 ) -> flams_ontology::narration::LazyDocRef<T> {
124 todo!()
125 }
126 fn add_term(
127 &mut self,
128 _symbol: Option<flams_ontology::uris::SymbolURI>,
129 _tm: flams_ontology::content::terms::Term,
130 ) -> Result<(), flams_ontology::content::terms::Term> {
131 todo!()
132 }
133 fn add_title(
134 &mut self,
135 _title: flams_ontology::DocumentRange,
136 ) -> Result<(), flams_ontology::DocumentRange> {
137 todo!()
138 }
139 fn add_type(
140 &mut self,
141 _tm: flams_ontology::content::terms::Term,
142 ) -> Result<(), flams_ontology::content::terms::Term> {
143 todo!()
144 }
145 fn close_args(
146 &mut self,
147 ) -> (
148 Vec<flams_ontology::content::terms::Arg>,
149 Option<flams_ontology::content::terms::Term>,
150 ) {
151 todo!()
152 }
153 fn close_complex_term(&mut self) -> Option<flams_ontology::content::terms::Term> {
154 todo!()
155 }
156 fn close_content(
157 &mut self,
158 ) -> Option<(
159 flams_ontology::uris::ModuleURI,
160 Vec<flams_ontology::content::declarations::OpenDeclaration<Unchecked>>,
161 )> {
162 todo!()
163 }
164 fn close_decl(
165 &mut self,
166 ) -> Option<(
167 Option<flams_ontology::content::terms::Term>,
168 Option<flams_ontology::content::terms::Term>,
169 )> {
170 todo!()
171 }
172 fn close_problem(&mut self) -> Option<ftml_extraction::prelude::ProblemState> {
173 todo!()
174 }
175 fn close_narrative(
176 &mut self,
177 ) -> Option<(
178 flams_ontology::uris::NarrativeURI,
179 Vec<flams_ontology::narration::DocumentElement<Unchecked>>,
180 )> {
181 todo!()
182 }
183 fn close_notation(&mut self) -> Option<ftml_extraction::prelude::NotationState> {
184 todo!()
185 }
186 fn close_paragraph(&mut self) -> Option<ftml_extraction::prelude::ParagraphState> {
187 todo!()
188 }
189 fn close_section(
190 &mut self,
191 ) -> Option<(
192 flams_ontology::uris::DocumentElementURI,
193 Option<flams_ontology::DocumentRange>,
194 Vec<flams_ontology::narration::DocumentElement<Unchecked>>,
195 )> {
196 todo!()
197 }
198 fn get_content_uri(&self) -> Option<&flams_ontology::uris::ModuleURI> {
199 todo!()
200 }
201 fn get_narrative_uri(&self) -> flams_ontology::uris::NarrativeURI {
202 expect_context::<NarrativeURI>()
203 }
204 fn with_problem<R>(
205 &mut self,
206 _then: impl FnOnce(&mut ftml_extraction::prelude::ProblemState) -> R,
207 ) -> Option<R> {
208 todo!()
209 }
210 fn close_gnote(&mut self) -> Option<GnoteState> {
211 todo!()
212 }
213 fn close_choice_block(&mut self) -> Option<ftml_extraction::prelude::ChoiceBlockState> {
214 todo!()
215 }
216 fn close_fillinsol(&mut self) -> Option<ftml_extraction::prelude::FillinsolState> {
217 todo!()
218 }
219 fn close_slide(
220 &mut self,
221 ) -> Option<Vec<flams_ontology::narration::DocumentElement<Unchecked>>> {
222 todo!()
223 }
224
225 fn add_definiendum(&mut self, _uri: flams_ontology::uris::SymbolURI) {}
226 fn push_fillinsol_case(&mut self, _case: flams_ontology::narration::problems::FillInSolOption) {
227 }
228 fn open_fillinsol(&mut self, _width: Option<f32>) {}
229 fn push_answer_class(
230 &mut self,
231 _id: Box<str>,
232 _kind: flams_ontology::narration::problems::AnswerKind,
233 ) {
234 }
235 fn push_problem_choice(&mut self, _correct: bool) {}
236 fn open_gnote(&mut self) {}
237 fn open_choice_block(&mut self, _multiple: bool, _styles: Box<[Box<str>]>) {}
238 fn open_args(&mut self) {}
239 fn open_complex_term(&mut self) {}
240 fn open_content(&mut self, _uri: flams_ontology::uris::ModuleURI) {}
241 fn open_decl(&mut self) {}
242 fn open_problem(&mut self, _uri: flams_ontology::uris::DocumentElementURI) {}
243 fn open_narrative(&mut self, _uri: Option<flams_ontology::uris::NarrativeURI>) {}
244 fn open_notation(&mut self) {}
245 fn open_slide(&mut self) {}
246 fn open_paragraph(
247 &mut self,
248 _uri: flams_ontology::uris::DocumentElementURI,
249 _fors: VecSet<flams_ontology::uris::SymbolURI>,
250 ) {
251 }
252 fn open_section(&mut self, _uri: flams_ontology::uris::DocumentElementURI) {}
253 fn set_document_title(&mut self, _title: Box<str>) {}
254}
255
256pub struct NodeAttrs<'n> {
257 elem: Cow<'n, Element>,
258 keys: SmallVec<String, 4>,
259}
260impl<'n> NodeAttrs<'n> {
261 pub(crate) fn new(elem: &'n Element) -> Self {
262 Self {
263 elem: Cow::Borrowed(elem),
264 keys: Self::attr_names(elem),
265 }
266 }
267
268 fn attr_names(e: &Element) -> SmallVec<String, 4> {
269 let mut ret = SmallVec::new();
270 for k in e.get_attribute_names() {
271 if let Some(s) = k.as_string() {
272 ret.push(s)
273 }
274 }
275 ret
276 }
277}
278impl Attributes for NodeAttrs<'_> {
279 type KeyIter<'a>
280 = std::iter::Map<std::slice::Iter<'a, String>, for<'b> fn(&'b String) -> &'b str>
281 where
282 Self: 'a;
283 type Value<'a>
284 = String
285 where
286 Self: 'a;
287 fn keys(&self) -> Self::KeyIter<'_> {
288 self.keys.iter().map(AsRef::as_ref)
289 }
290 fn value(&self, key: &str) -> Option<Self::Value<'_>> {
291 self.elem.get_attribute(key)
292 }
293 fn set(&mut self, key: &str, value: &str) {
294 let _ = self.elem.set_attribute(key, value);
295 }
296 fn take(&mut self, key: &str) -> Option<String> {
297 let r = self.elem.get_attribute(key);
298 let _ = self.elem.remove_attribute(key);
299 r
300 }
301}