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}