Skip to main content

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}