flams_router_content/
toc.rs1use 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 children, ..
22 } => {
23 let old = std::mem::replace(&mut curr, children.iter());
24 stack.push((old, None));
25 ret.push(TOCElem::Slide );
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, 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, });
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 { .. } => (), }
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}