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