1use std::collections::HashMap;
11
12mod larst_writer;
13mod node_categories;
14mod restructuredtext_transforms;
15mod tree_zipper;
16use tree_zipper::TreeZipper;
17pub mod tree_node;
18use tree_node::TreeNode;
19pub mod tree_node_types;
20use tree_node_types::TreeNodeType;
21pub mod directives;
22mod hyperref_data;
23use hyperref_data::{HyperrefData, ANON_REF_LABEL_PREFIX, ANON_REF_LABEL_SUFFIX};
24mod class_data;
25use class_data::ClassData;
26mod section_data;
27use section_data::SectionData;
28mod walkers;
29
30use crate::common::{
31 EnumDelims, EnumKind, FootnoteKind, HTMLAlignment, HorizontalAlignment, Length, MetricType,
32 NodeId, SectionLineStyle, TableColWidths, ToCBacklinks,
33};
34
35mod tests;
36
37pub struct DocTree {
42
43 filename_stem: String,
45
46 file_folder: String,
49
50 tree: TreeZipper,
52
53 node_count: NodeId,
59
60 hyperref_data: HyperrefData,
62
63 class_data: ClassData,
65
66 section_data: SectionData,
68}
69
70use std::path::PathBuf;
71
72impl DocTree {
74
75 pub fn new(doc_name: PathBuf) -> Self {
77 let root_id: NodeId = 0;
78 let root_data = TreeNodeType::Document;
79 let root_node = TreeNode::new(root_data, root_id, None, None);
80
81 let file_stem: String = if let Some(path_os_str) = doc_name.file_stem() {
82 if let Some(path_str) = path_os_str.to_str() {
83 path_str.to_string()
84 } else {
85 panic!("Invalid unicode in file path. Computer says no...")
86 }
87 } else {
88 String::new()
90 };
91
92 let file_folder = if let Some(parent) = doc_name.parent() {
93 if let Some(path_str) = parent.to_str() {
94 path_str.to_string()
95 } else {
96 panic!("Source folder path could not be converted to a string. Computer says no...")
97 }
98 } else {
99 String::new()
101 };
102
103 DocTree {
104 filename_stem: file_stem,
105 file_folder: file_folder,
106 tree: TreeZipper::new(root_node, None, None),
107 node_count: root_id + 1,
108 hyperref_data: HyperrefData::new(),
109 class_data: ClassData::new(),
110 section_data: SectionData::new(),
111 }
112 }
113
114 pub fn n_of_nodes(&self) -> NodeId {
116 self.node_count
117 }
118
119 pub fn print_tree(&self) {
122 eprintln!("The Document Tree\n=================");
123 eprintln!("{:#?}", self.tree)
124 }
125
126 fn print_node(&self) {
128 eprintln!("{:#?}", self.tree.shared_node())
129 }
130
131 fn print_node_id(&self) {
133 eprintln!("{:#?}", self.tree.node_id())
134 }
135
136 pub fn node_count(&self) -> NodeId {
138 self.node_count
139 }
140
141 pub fn print_internal_labels(&self) {
144 eprintln!(
145 "{:#?}",
146 self.hyperref_data
147 .shared_accumulated_internal_target_label()
148 );
149 }
150
151 pub fn focus_on_parent(mut self) -> Self {
153 self.tree = match self.tree.focus_on_parent() {
154 Ok(tree) => tree,
155 Err(tree) => {
156 eprintln!("INFO: Tried focusing on node parent but no parent found.\n");
157 tree
158 }
159 };
160
161 self
162 }
163
164 pub fn push_data_and_focus(mut self, mut node_data: TreeNodeType) -> Result<Self, Self> {
168 let target_labels = self.hyperref_actions(&mut node_data);
169 let classes = self.classes();
170 match self
171 .tree
172 .push_data_and_focus(node_data, self.node_count, target_labels, classes)
173 {
174 Ok(tree) => {
175 self.node_count += 1;
176 self.tree = tree;
177 Ok(self)
178 }
179 Err(tree) => {
180 self.tree = tree;
181 Err(self)
182 }
183 }
184 }
185
186 pub fn push_data(mut self, mut node_data: TreeNodeType) -> Result<Self, Self> {
190 let target_labels = self.hyperref_actions(&mut node_data);
191 let classes = self.classes();
192 match self
193 .tree
194 .push_data(node_data, self.node_count, target_labels, classes)
195 {
196 Ok(tree) => {
197 self.tree = tree;
198 self.node_count += 1;
199 Ok(self)
200 }
201 Err(tree) => {
202 self.tree = tree;
203 Err(self)
204 }
205 }
206 }
207
208 pub fn push_child(&mut self, mut node: TreeNode) -> Result<(), TreeNode> {
211
212 let incoming_target_labels = self.hyperref_actions(node.mut_data());
213 node.set_target_label(incoming_target_labels);
214 match self.tree.push_child(node) {
215 Ok(()) => {
216 self.node_count += 1;
217 Ok(())
218 }
219 Err(node) => Err(node),
220 }
221 }
222 pub fn pop_child(&mut self) -> Option<TreeNode> {
224 match self.tree.pop_child() {
225 Some(node) => Some(node),
226 None => None,
227 }
228 }
229
230 fn hyperref_actions(&mut self, node_data: &mut TreeNodeType) -> Option<Vec<String>> {
233
234 use crate::common::normalize_refname;
235
236 let accumulated_target_label = self.hyperref_data.mut_accumulated_internal_target_label();
238 let mut target_labels: Vec<String> = if accumulated_target_label.is_empty() {
239 Vec::new()
240 } else {
241 match node_data {
242 TreeNodeType::EmptyLine | TreeNodeType::WhiteSpace { .. } => Vec::new(),
243 _ => {
244 let labels = accumulated_target_label.drain(..).collect();
245 accumulated_target_label.clear();
246 labels
247 }
248 }
249 };
250
251 match node_data {
254 TreeNodeType::Citation { label, .. } => {
255 let normalized_refname = normalize_refname(label);
256 self.add_target(&normalized_refname, self.node_count);
257 target_labels.push(normalized_refname);
258 }
259 TreeNodeType::CitationReference { displayed_text, .. } => {
260 let normalized_refname = normalize_refname(displayed_text);
261 self.add_reference(&normalized_refname, self.node_count)
262 }
263 TreeNodeType::Footnote { target, label, kind, .. } => {
264 match kind {
265 FootnoteKind::Manual => {
266 let normalized_refname = normalize_refname(label);
267 target_labels.push(normalized_refname);
268 }
269 FootnoteKind::AutoNumbered => {
270 match self.new_autonumber_footnote_label() {
271 Some(number) => {
272 *target = number.clone();
273 *label = number.clone();
274 target_labels.push(number)
275 }
276 None => ()
277 }
278 }
279 FootnoteKind::SimpleRefName => {
280 match self.new_autonumber_footnote_label() {
281 Some(number) => {
282 *target = number.clone();
283 *label = number.clone();
284 target_labels.push(number)
285 }
286 None => ()
287 }
288 }
289 FootnoteKind::AutoSymbol => {
290 match self.new_symbolic_footnote_label() {
291 Some(symbol) => {
292 *target = symbol.clone();
293 *label = symbol.clone();
294 target_labels.push(symbol)
295 }
296 None => ()
297 }
298 }
299 };
300 for label in target_labels.iter() {
301 self.add_target(label, self.node_count)
302 }
303 if let FootnoteKind::AutoSymbol = kind {
304 self.increment_symbolic_footnotes();
305 }
306 }
307 TreeNodeType::FootnoteReference { displayed_text, target_label, kind } => {
308 match kind {
309 FootnoteKind::Manual => target_labels.push(
310 crate::common::normalize_refname(displayed_text)
311 ),
312 FootnoteKind::AutoNumbered => match self.new_autonumber_footnote_ref_label() {
313 Some(label) => {
314 *displayed_text = label.clone();
315 *target_label = label.clone();
316 target_labels.push(label)
317 },
318 None => return None
319 },
320 FootnoteKind::SimpleRefName => {
321 match self.new_autonumber_footnote_ref_label() {
322 Some(label) => {
323 *target_label = label.clone();
324 target_labels.push(label)
325 },
326 None => return None
327 }
328 target_labels.push(crate::common::normalize_refname(displayed_text));
329 },
330 FootnoteKind::AutoSymbol => match self.new_symbolic_footnote_label() {
331 Some(label) => target_labels.push(label),
332 None => return None
333 }
334 };
335 for label in target_labels.iter() {
336 self.add_reference(&label, self.node_count)
337 }
338 },
339 TreeNodeType::ExternalHyperlinkTarget { uri, target, .. } => {
340 let normalized_refname = normalize_refname(target);
341 target_labels.push(normalized_refname);
342 for label in target_labels.iter() {
343 self.add_target(label,self.node_count);
344 }
345 }
346 TreeNodeType::IndirectHyperlinkTarget {
347 target,
348 indirect_target,
349 ..
350 } => {
351 let normalized_target_refname = normalize_refname(target);
352 let normalized_indirect_refname = normalize_refname(target);
353 for label in target_labels.iter() {
354 self.add_target(
355 label,
356 self.node_count,
357 );
358 }
359 self.add_reference(
360 &normalize_refname(normalized_indirect_refname.as_str()),
361 self.node_count,
362 );
363 }
364 TreeNodeType::Section {
365 title_text,
366 level,
367 line_style,
368 } => {
369 target_labels.push(normalize_refname(title_text));
370 for label in target_labels.iter() {
371 self.add_target(label,self.node_count);
372 }
373 self.section_data.add_section_level(*line_style);
374 if *level > self.section_data.highest_encountered_section_level() {
375 self.section_data.increment_encountered_section_number();
376 }
377 }
378 _ => for label in target_labels.iter() {
379 self.add_target(label,self.node_count);
380 },
381 };
382 if target_labels.is_empty() { None } else { Some(target_labels) }
383 }
384
385
386 fn classes(&mut self) -> Option<Vec<String>> {
388 let classes = self.class_data.mut_classes();
389 if classes.is_empty() {
390 None
391 } else {
392 Some(classes.drain(..).collect())
393 }
394 }
395
396 pub fn shared_node(&self) -> &TreeNode {
398 self.tree.shared_node()
399 }
400
401 pub fn mut_node(&mut self) -> &mut TreeNode {
403 self.tree.mut_node()
404 }
405
406 pub fn shared_children(&self) -> Option<&Vec<TreeNode>> {
408 if let Some(children) = self.tree.shared_children() {
409 Some(children)
410 } else {
411 None
412 }
413 }
414
415 pub fn mut_children(&mut self) -> Option<&mut Vec<TreeNode>> {
417 if let Some(children) = self.tree.mut_children() {
418 Some(children)
419 } else {
420 None
421 }
422 }
423
424 pub fn shared_node_data(&self) -> &TreeNodeType {
427 self.tree.shared_node().shared_data()
428 }
429
430 pub fn mut_node_data(&mut self) -> &mut TreeNodeType {
433 self.tree.mut_node().mut_data()
434 }
435
436 pub fn get_child_data(&self, index: usize) -> &TreeNodeType {
438 if let Some(children) = self.tree.shared_node().shared_children() {
439 match children.get(index) {
440 Some(node) => node.shared_data(),
441 None => {
442 eprintln!("Focused on node does not have as many children as is implied.\nComputer says no...\n");
443 panic!()
444 }
445 }
446 } else {
447 panic!("Cannot retrieve shared child data from a node that cannot have children. Computer says no...")
448 }
449 }
450
451 pub fn n_of_children(&self) -> usize {
452 self.tree.n_of_children()
453 }
454
455 pub fn get_mut_child_data(&mut self, index: usize) -> &mut TreeNodeType {
457 if let Some(children) = self.tree.mut_node().mut_children() {
458 match children.get_mut(index) {
459 Some(node) => node.mut_data(),
460 None => {
461 eprintln!("Focused on node does not have as many children as is implied.\nComputer says no...\n");
462 panic!()
463 }
464 }
465 } else {
466 panic!("Cannot retrieve mutable child data from a node that cannot have children. Computer says no...")
467 }
468 }
469
470 pub fn shared_child(&self, index: usize) -> Option<&TreeNode> {
472 if let Some(children) = self.tree.shared_node().shared_children() {
473 match children.get(index) {
474 Some(node) => Some(node),
475 None => {
476 eprintln!("Focused on node does not have as many children as is implied. Computer says no...");
477 None
478 }
479 }
480 } else {
481 eprintln!(
482 "Cannot retrieve child from a node that cannot have children. Computer says no..."
483 );
484 None
485 }
486 }
487
488 pub fn mut_child(&mut self, index: usize) -> Option<&mut TreeNode> {
490 if let Some(children) = self.tree.mut_node().mut_children() {
491 match children.get_mut(index) {
492 Some(node) => Some(node),
493 None => {
494 eprintln!("Focused on node does not have as many children as is implied. Computer says no...");
495 None
496 }
497 }
498 } else {
499 eprintln!(
500 "Cannot retrieve child from a node that cannot have children. Computer says no..."
501 );
502 None
503 }
504 }
505
506 pub fn shared_sibling_data(&self, sibling_index: usize) -> Option<&TreeNodeType> {
508 if let Some(sibling_data) = self.tree.shared_sibling_data(sibling_index) {
509 Some(sibling_data)
510 } else {
511 eprintln!("Warning: No sibling with index {}...\n", sibling_index);
512 None
513 }
514 }
515
516 pub fn index_in_parent(&self) -> Option<usize> {
518 self.tree.index_in_parent()
519 }
520
521 pub fn append_children(&mut self, nodes: &mut Children) {
524 let children = nodes.len() as NodeId; self.tree.append_children(nodes);
526 self.node_count += children;
527 }
528
529 pub fn has_target_label(&self, label_to_be_inspected_for: &str) -> bool {
531 self.hyperref_data
532 .shared_targets()
533 .contains_key(label_to_be_inspected_for)
534 }
535
536 pub fn has_reference_label(&self, label_to_be_inspected_for: &str) -> bool {
538 self.hyperref_data
539 .shared_references()
540 .contains_key(label_to_be_inspected_for)
541 }
542
543 pub fn current_node_id(&self) -> NodeId {
545 self.tree.node_id()
546 }
547
548 fn add_target(&mut self, label: &String, id: NodeId) {
551 match self.hyperref_data.mut_targets().insert(label.clone(), id) {
552 Some(node_id) => {
553 eprintln!("Found an existing node with the target label \"{}\".\nReplacing duplicate node id value {} with {}...\n", label, node_id, id);
554 }
555 None => {}
556 };
557 }
558
559 fn add_reference(&mut self, label: &String, id: NodeId) {
562 match self
563 .hyperref_data
564 .mut_references()
565 .get_mut(label)
566 {
567 Some(node_ids) => {
568 node_ids.push(id);
569 },
570 None => {
571 self.hyperref_data.mut_references().insert(label.clone(), vec![id]);
572 }
573 };
574 }
575
576 pub fn push_to_internal_target_stack(&mut self, label: String) {
580 self.hyperref_data.add_internal_target_label(label);
581 }
582
583 pub fn n_of_symbolic_footnotes(&self) -> u32 {
585 self.hyperref_data.n_of_symbolic_footnotes()
586 }
587
588 pub fn n_of_symbolic_footnote_refs(&self) -> u32 {
590 self.hyperref_data.n_of_symbolic_footnote_refs()
591 }
592
593 pub fn increment_symbolic_footnotes(&mut self) {
595 self.hyperref_data.increment_symbolic_footnote_counter_by(1);
596 }
597
598 pub fn increment_symbolic_footnote_refs(&mut self) {
600 self.hyperref_data
601 .increment_symbolic_footnote_ref_counter_by(1);
602 }
603
604 pub fn increment_anon_targets(&mut self) {
606 self.hyperref_data.increment_anonymous_target_counter_by(1);
607 }
608
609 pub fn increment_anon_references(&mut self) {
611 self.hyperref_data
612 .increment_anonymous_target_ref_counter_by(1);
613 }
614
615 pub fn next_anon_target_n(&mut self) -> u32 {
617 self.increment_anon_targets();
618 self.hyperref_data.n_of_anon_targets()
619 }
620
621 pub fn next_anon_reference_n(&mut self) -> u32 {
623 self.increment_anon_references();
624 self.hyperref_data.n_of_anon_target_refs()
625 }
626
627 pub fn next_anon_target_label(&mut self) -> String {
629 format!(
630 "{}{}{}",
631 ANON_REF_LABEL_PREFIX,
632 self.next_anon_target_n(),
633 ANON_REF_LABEL_SUFFIX
634 )
635 }
636
637 pub fn next_anon_reference_label(&mut self) -> String {
639 format!(
640 "{}{}{}",
641 ANON_REF_LABEL_PREFIX,
642 self.next_anon_reference_n(),
643 ANON_REF_LABEL_SUFFIX
644 )
645 }
646
647 pub fn shared_targets(&self) -> &HashMap<String, NodeId> {
649 self.hyperref_data.shared_targets()
650 }
651
652 pub fn mut_targets(&mut self) -> &mut HashMap<String, NodeId> {
654 self.hyperref_data.mut_targets()
655 }
656
657 pub fn shared_references(&self) -> &HashMap<String, Vec<NodeId>> {
659 self.hyperref_data.shared_references()
660 }
661
662 pub fn mut_references(&mut self) -> &mut HashMap<String, Vec<NodeId>> {
664 self.hyperref_data.mut_references()
665 }
666
667 pub fn new_section_data(
676 &self,
677 title_text: &str,
678 section_style: SectionLineStyle,
679 ) -> TreeNodeType {
680 let section_level = self.section_data.line_style_section_level(§ion_style);
681 TreeNodeType::Section {
682 level: section_level,
683 title_text: title_text.to_string(),
684 line_style: section_style,
685 }
686 }
687
688 pub fn add_section(mut self, title_text: &str, section_style: SectionLineStyle) -> Self {
692 let section_data = self.new_section_data(title_text, section_style);
693
694 self = match self.push_data(section_data) {
695 Ok(tree) | Err(tree) => tree,
696 };
697 self
698 }
699
700 pub fn walk_to_parent_section_level(mut self, level: usize) -> Self {
702 self.tree = self.tree.walk_to_parent_section_level(level);
703 self
704 }
705
706 pub fn shared_parent_ref(&self) -> Option<&TreeZipper> {
708 self.tree.shared_parent_ref()
709 }
710
711 pub fn shared_data(&self) -> &TreeNodeType {
713 self.tree.shared_data()
714 }
715
716 pub fn shared_parent_data(&self) -> Option<&TreeNodeType> {
718 if let Some(parent_ref) = self.shared_parent_ref() {
719 Some(parent_ref.shared_data())
720 } else {
721 None
722 }
723 }
724
725 pub fn new_symbolic_footnote_label (&self) -> Option<String> {
730 let n = self.n_of_symbolic_footnotes() as usize; let n_of_symbols = crate::common::FOOTNOTE_SYMBOLS.len();
736
737 let passes = n / n_of_symbols;
738 let index = n % n_of_symbols;
739 let symbol: char = match crate::common::FOOTNOTE_SYMBOLS.get(index) {
740 Some(symb) => *symb,
741 None => {
742 eprintln!("No footnote symbol with index {}!", index);
743 return None;
744 }
745 };
746 let label: String = vec![symbol; passes + 1].iter().collect();
747 return Some(label)
748 }
749
750 pub fn new_symbolic_footnote_ref_label (&self) -> Option<String> {
755 let n = self.n_of_symbolic_footnote_refs() as usize; let n_of_symbols = crate::common::FOOTNOTE_SYMBOLS.len();
761
762 let passes = n / n_of_symbols;
763 let index = n % n_of_symbols;
764 let symbol: char = match crate::common::FOOTNOTE_SYMBOLS.get(index) {
765 Some(symb) => *symb,
766 None => {
767 eprintln!("No footnote symbol with index {}!", index);
768 return None;
769 }
770 };
771 let label: String = vec![symbol; passes + 1].iter().collect();
772 return Some(label)
773 }
774
775 pub fn new_autonumber_footnote_label (&self) -> Option<String>{
779 for n in 1..=crate::common::EnumAsInt::MAX {
780 let n_str = n.to_string();
781 if self.has_target_label(n_str.as_str()) {
782 continue;
783 }
784 return Some(n_str);
785 }
786 eprintln!("All possible footnote numbers in use. Computer says no...");
787 return None;
788 }
789
790 pub fn new_autonumber_footnote_ref_label (&self) -> Option<String>{
794 for n in 1..=crate::common::EnumAsInt::MAX {
795 let n_str = n.to_string();
796 if self.has_reference_label(n_str.as_str()) {
797 continue;
798 }
799 return Some(n_str);
800 }
801 eprintln!("All possible footnote numbers in use. Computer says no...");
802 return None;
803 }
804}
805
806type Children = Vec<TreeNode>;