flams_router_content/toc.rs
1use flams_math_archives::backend::LocalBackend;
2use flams_utils::vecmap::VecSet;
3use ftml_ontology::{
4 narrative::{
5 documents::{Document, TocElem},
6 elements::{DocumentElement, Problem, Section},
7 },
8 utils::Css,
9};
10
11pub async fn from_document(doc: Document) -> (Box<[Css]>, Box<[TocElem]>) {
12 let (css, e) = from_document_i(doc, String::new(), VecSet::default()).await;
13 (css.0.into_boxed_slice(), e)
14}
15
16fn from_document_i(
17 doc: Document,
18 mut prefix: String,
19 mut css: VecSet<Css>,
20) -> impl Future<Output = (VecSet<Css>, Box<[TocElem]>)> + Send {
21 use flams_system::backend::backend;
22 async move {
23 let mut curr = doc.elements.iter();
24 let mut stack = Vec::new();
25 let mut ret = Vec::new();
26 loop {
27 while let Some(elem) = curr.next() {
28 match elem {
29 DocumentElement::Slide(ftml_ontology::narrative::elements::Slide {
30 /*uri,*/ children,
31 ..
32 }) => {
33 let old = std::mem::replace(&mut curr, children.iter());
34 stack.push((old, None));
35 ret.push(TocElem::Slide /*{uri:uri.clone()}*/);
36 }
37 DocumentElement::Section(Section {
38 uri,
39 title,
40 children,
41 ..
42 }) => {
43 let old = std::mem::replace(&mut curr, children.iter());
44 stack.push((
45 old,
46 Some(TocElem::Section {
47 title: title.clone(), // TODO
48 id: prefix.clone(),
49 uri: uri.clone(),
50 children: std::mem::take(&mut ret),
51 }),
52 ));
53 prefix = if prefix.is_empty() {
54 uri.name().last().to_string()
55 } else {
56 format!("{prefix}/{}", uri.name().last())
57 };
58 }
59 DocumentElement::DocumentReference { uri, target, .. } => {
60 let Ok(d) = backend()
61 .get_document_async::<flams_system::TokioEngine>(target)
62 .await
63 else {
64 continue;
65 };
66 let title = d.title.clone();
67 let mut id = prefix.clone();
68
69 prefix = if prefix.is_empty() {
70 uri.name().last().to_string()
71 } else {
72 format!("{prefix}/{}", uri.name().last())
73 };
74 let fut =
75 Box::pin(from_document_i(d, prefix.clone(), std::mem::take(&mut css)))
76 as std::pin::Pin<
77 Box<dyn Future<Output = (_, Box<[TocElem]>)> + Send>,
78 >;
79 let (ncss, children) = fut.await;
80 css = ncss;
81
82 std::mem::swap(&mut prefix, &mut id);
83 if !children.is_empty() {
84 ret.push(TocElem::Inputref {
85 uri: target.clone(),
86 title,
87 id,
88 children: children.into_vec(),
89 });
90 }
91
92 /*
93 let old = std::mem::replace(&mut curr, d.elements.iter());
94 stack.push((
95 old,
96 Some(TocElem::Inputref {
97 id: prefix.clone(),
98 uri: target.clone(),
99 title,
100 children: std::mem::take(&mut ret),
101 }),
102 ));
103 prefix = if prefix.is_empty() {
104 uri.name().last().to_string()
105 } else {
106 format!("{prefix}/{}", uri.name().last())
107 };
108 */
109 }
110 DocumentElement::Paragraph(p) => {
111 ret.push(TocElem::Paragraph {
112 styles: p.styles.clone().into_vec(),
113 kind: p.kind, /*,uri:p.uri.clone()*/
114 });
115 }
116 DocumentElement::Module { children, .. }
117 | DocumentElement::Morphism { children, .. }
118 | DocumentElement::MathStructure { children, .. }
119 | DocumentElement::Extension { children, .. }
120 | DocumentElement::Problem(Problem { children, .. }) => {
121 let old = std::mem::replace(&mut curr, children.iter());
122 stack.push((old, None));
123 }
124 DocumentElement::SkipSection(children) => {
125 let old = std::mem::replace(&mut curr, children.iter());
126 stack.push((
127 old,
128 Some(TocElem::SkippedSection {
129 children: std::mem::take(&mut ret),
130 }),
131 ));
132 }
133 DocumentElement::SymbolDeclaration(_)
134 | DocumentElement::SymbolReference { .. }
135 | DocumentElement::Notation { .. }
136 | DocumentElement::VariableNotation { .. }
137 | DocumentElement::VariableDeclaration(_)
138 | DocumentElement::Definiendum { .. }
139 | DocumentElement::VariableReference { .. }
140 | DocumentElement::Term { .. }
141 | DocumentElement::UseModule { .. }
142 | DocumentElement::ImportModule { .. } => (), //_ => ()
143 }
144 }
145 match stack.pop() {
146 None => break,
147 Some((
148 _,
149 Some(TocElem::Inputref {
150 /*mut id,
151 uri,
152 title,
153 mut children*/
154 ..
155 }),
156 )) => unreachable!(), /*{
157 curr = iter;
158 std::mem::swap(&mut prefix, &mut id);
159 std::mem::swap(&mut ret, &mut children);
160 if !children.is_empty() {
161 ret.push(TocElem::Inputref {
162 id,
163 uri,
164 title,
165 children,
166 });
167 }
168 }*/
169 Some((
170 iter,
171 Some(TocElem::Section {
172 mut id,
173 uri,
174 title,
175 mut children,
176 }),
177 )) => {
178 curr = iter;
179 std::mem::swap(&mut prefix, &mut id);
180 std::mem::swap(&mut ret, &mut children);
181 if title.is_some() || !children.is_empty() {
182 ret.push(TocElem::Section {
183 id,
184 uri,
185 title,
186 children,
187 });
188 }
189 }
190 Some((iter, Some(TocElem::SkippedSection { mut children }))) => {
191 curr = iter;
192 std::mem::swap(&mut ret, &mut children);
193 if !children.is_empty() {
194 ret.push(TocElem::SkippedSection { children });
195 }
196 }
197 Some((iter, _)) => curr = iter,
198 }
199 }
200 (css, ret.into_boxed_slice())
201 }
202}