flams_router_content/
toc.rs

1use crate::ssr::insert_base_url;
2
3use super::ssr::backend;
4use flams_ontology::narration::{
5    DocumentElement, NarrationTrait, documents::Document, problems::Problem, sections::Section,
6};
7use flams_system::backend::Backend;
8use flams_utils::{CSS, unwrap, vecmap::VecSet};
9use ftml_viewer_components::components::TOCElem;
10
11pub async fn from_document(doc: &Document) -> (Vec<CSS>, Vec<TOCElem>) {
12    let mut curr = doc.children().iter();
13    let mut prefix = String::new();
14    let mut stack = Vec::new();
15    let mut ret = Vec::new();
16    let mut css = VecSet::new();
17    loop {
18        while let Some(elem) = curr.next() {
19            match elem {
20                DocumentElement::Slide {
21                    /*uri,*/ children, ..
22                } => {
23                    let old = std::mem::replace(&mut curr, children.iter());
24                    stack.push((old, None));
25                    ret.push(TOCElem::Slide /*{uri:uri.clone()}*/);
26                }
27                DocumentElement::Section(Section {
28                    uri,
29                    title,
30                    children,
31                    ..
32                }) => {
33                    let old = std::mem::replace(&mut curr, children.iter());
34                    let title = if let Some(title) = title {
35                        if let Some((c, h)) = backend!(!get_html_fragment(uri.document(), *title)) {
36                            for c in c {
37                                css.insert(c);
38                            }
39                            Some(h)
40                        } else {
41                            None
42                        }
43                    } else {
44                        None
45                    };
46                    stack.push((
47                        old,
48                        Some(TOCElem::Section {
49                            title, // TODO
50                            id: prefix.clone(),
51                            uri: uri.clone(),
52                            children: std::mem::take(&mut ret),
53                        }),
54                    ));
55                    prefix = if prefix.is_empty() {
56                        uri.name().last_name().to_string()
57                    } else {
58                        format!("{prefix}/{}", uri.name().last_name())
59                    };
60                }
61                DocumentElement::DocumentReference { id, target, .. } if target.is_resolved() => {
62                    let d = unwrap!(target.get());
63                    let title = d.title().map(ToString::to_string);
64                    let uri = d.uri().clone();
65                    let old = std::mem::replace(&mut curr, d.children().iter());
66                    stack.push((
67                        old,
68                        Some(TOCElem::Inputref {
69                            id: prefix.clone(),
70                            uri,
71                            title,
72                            children: std::mem::take(&mut ret),
73                        }),
74                    ));
75                    prefix = if prefix.is_empty() {
76                        id.name().last_name().to_string()
77                    } else {
78                        format!("{prefix}/{}", id.name().last_name())
79                    };
80                }
81                DocumentElement::Paragraph(p) => {
82                    ret.push(TOCElem::Paragraph {
83                        styles: p.styles.clone().into_vec(),
84                        kind: p.kind, /*,uri:p.uri.clone()*/
85                    });
86                }
87                DocumentElement::Module { children, .. }
88                | DocumentElement::Morphism { children, .. }
89                | DocumentElement::MathStructure { children, .. }
90                | DocumentElement::Extension { children, .. }
91                | DocumentElement::Problem(Problem { children, .. }) => {
92                    let old = std::mem::replace(&mut curr, children.iter());
93                    stack.push((old, None));
94                }
95                DocumentElement::SkipSection(children) => {
96                    let old = std::mem::replace(&mut curr, children.iter());
97                    stack.push((
98                        old,
99                        Some(TOCElem::SkippedSection {
100                            children: std::mem::take(&mut ret),
101                        }),
102                    ));
103                }
104                DocumentElement::SetSectionLevel(_)
105                | DocumentElement::SymbolDeclaration(_)
106                | DocumentElement::SymbolReference { .. }
107                | DocumentElement::Notation { .. }
108                | DocumentElement::VariableNotation { .. }
109                | DocumentElement::Variable(_)
110                | DocumentElement::Definiendum { .. }
111                | DocumentElement::VariableReference { .. }
112                | DocumentElement::TopTerm { .. }
113                | DocumentElement::UseModule { .. }
114                | DocumentElement::ImportModule { .. }
115                | DocumentElement::DocumentReference { .. } => (), //_ => ()
116            }
117        }
118        match stack.pop() {
119            None => break,
120            Some((
121                iter,
122                Some(TOCElem::Inputref {
123                    mut id,
124                    uri,
125                    title,
126                    mut children,
127                }),
128            )) => {
129                curr = iter;
130                std::mem::swap(&mut prefix, &mut id);
131                std::mem::swap(&mut ret, &mut children);
132                if !children.is_empty() {
133                    ret.push(TOCElem::Inputref {
134                        id,
135                        uri,
136                        title,
137                        children,
138                    });
139                }
140            }
141            Some((
142                iter,
143                Some(TOCElem::Section {
144                    mut id,
145                    uri,
146                    title,
147                    mut children,
148                }),
149            )) => {
150                curr = iter;
151                std::mem::swap(&mut prefix, &mut id);
152                std::mem::swap(&mut ret, &mut children);
153                if title.is_some() || !children.is_empty() {
154                    ret.push(TOCElem::Section {
155                        id,
156                        uri,
157                        title,
158                        children,
159                    });
160                }
161            }
162            Some((iter, Some(TOCElem::SkippedSection { mut children }))) => {
163                curr = iter;
164                std::mem::swap(&mut ret, &mut children);
165                if !children.is_empty() {
166                    ret.push(TOCElem::SkippedSection { children });
167                }
168            }
169            Some((iter, _)) => curr = iter,
170        }
171    }
172    (insert_base_url(css.0), ret)
173}