rustla/doctree/
restructuredtext_transforms.rs

1/*!
2A submodule that defines the transforms performed for each node type,
3before the tree is printed. These include things like transforming the
4second child of a `Figure` node to a `Caption`, if it is a `Paragraph`.
5
6Copyright © 2020 Santtu Söderholm
7*/
8use crate::doctree::tree_node::TreeNode;
9use crate::doctree::tree_zipper::TreeZipper;
10use crate::doctree::DocTree;
11
12impl DocTree {
13    /// Modifies `self.tree` with the known reStrucuturedText transforms.
14    pub fn perform_restructuredtext_transforms(mut self) -> Self {
15        self = self.walk_to_root();
16        self.tree = self.tree.perform_restructuredtext_transforms();
17        self = self.walk_to_root();
18        self
19    }
20}
21
22impl TreeZipper {
23    /// Recursively modifies the data of `self.node` and its children,
24    /// based on the node type `self.node.data`.
25    pub fn perform_restructuredtext_transforms(mut self) -> Self {
26        self.mut_node().perform_restructuredtext_transforms();
27        self
28    }
29}
30
31impl TreeNode {
32    /// Transforms `self.data` into a different type based on its current value.
33    /// This is where the recursion really kicks in.
34    pub fn perform_restructuredtext_transforms(&mut self) {
35        use crate::doctree::tree_node_types::TreeNodeType;
36
37        match self.mut_data() {
38            TreeNodeType::Abbreviation { .. } => {}
39            TreeNodeType::AbsoluteURI { .. } => {}
40            TreeNodeType::Acronym { .. } => {}
41            TreeNodeType::Address => {}
42            TreeNodeType::Admonition { .. } => {}
43            TreeNodeType::Attribution { .. } => {}
44            TreeNodeType::Author { .. } => {}
45            TreeNodeType::Authors { .. } => {}
46            TreeNodeType::AutomaticSectionNumbering { .. } => {}
47            TreeNodeType::BlockQuote { .. } => {}
48            TreeNodeType::BulletList { .. } => {}
49            TreeNodeType::BulletListItem { .. } => {}
50            TreeNodeType::Caption { .. } => {}
51            TreeNodeType::Citation { .. } => {}
52            TreeNodeType::CitationReference { .. } => {}
53            TreeNodeType::Class { .. } => {}
54            TreeNodeType::Classifier { .. } => {}
55            TreeNodeType::Code { .. } => {}
56            TreeNodeType::ColSpec { .. } => {}
57            TreeNodeType::Comment { .. } => {}
58            TreeNodeType::CompoundParagraph { .. } => {}
59            TreeNodeType::Contact { .. } => {}
60            TreeNodeType::Container { .. } => {}
61            TreeNodeType::Copyright { .. } => {}
62            TreeNodeType::CSVTable { .. } => {}
63            TreeNodeType::Date => {}
64            TreeNodeType::Decoration => {}
65            TreeNodeType::Definition => {}
66            TreeNodeType::DefinitionList { .. } => {}
67            TreeNodeType::DefinitionListItem { .. } => {}
68            TreeNodeType::Description => {}
69            TreeNodeType::DocInfo => {}
70            TreeNodeType::DoctestBlock { .. } => {}
71            TreeNodeType::Document { .. } => {}
72            TreeNodeType::Emphasis { .. } => {}
73            TreeNodeType::EmptyLine => {}
74            TreeNodeType::Entry { .. } => {}
75            TreeNodeType::EnumeratedList { .. } => {}
76            TreeNodeType::EnumeratedListItem { .. } => {}
77            TreeNodeType::ExternalHyperlinkTarget { .. } => {}
78            TreeNodeType::Field => {}
79            TreeNodeType::FieldBody { .. } => {}
80            TreeNodeType::FieldList { .. } => {}
81            TreeNodeType::FieldListItem { .. } => {}
82            TreeNodeType::Figure { .. } => {
83                if let Some(children) = self.mut_children() {
84                    if let Some(child) = children.get_mut(1) {
85                        if let TreeNodeType::Paragraph { indent } = child.mut_data() {
86                            // Transform paragraph data into a caption
87                            *child.mut_data() = TreeNodeType::Caption { indent: *indent };
88                        }
89                    } else {
90                        // Do nothing
91                    }
92                }
93            }
94            TreeNodeType::Footer { .. } => {}
95            TreeNodeType::Footnote { .. } => {}
96            TreeNodeType::FootnoteReference { .. } => {}
97            TreeNodeType::Header { .. } => {}
98            TreeNodeType::Generated => {}
99            TreeNodeType::Image { .. } => {}
100            TreeNodeType::Include { .. } => {}
101            TreeNodeType::IndirectHyperlinkTarget { .. } => {}
102            TreeNodeType::Inline { .. } => {}
103            TreeNodeType::InlineTarget { .. } => {}
104            TreeNodeType::InterpretedText { .. } => {}
105            TreeNodeType::Label { .. } => {}
106            TreeNodeType::Legend { .. } => {}
107            TreeNodeType::Line { .. } => {}
108            TreeNodeType::LineBlock { .. } => {}
109            TreeNodeType::ListTable { .. } => {
110                // Reconstruct the contained bullet list into a table
111                let rows: Vec<TreeNodeType> = Vec::new();
112
113                if let Some(children) = self.mut_children() {
114                    if let Some(bullet_list) = children.get_mut(0) {
115                        if let TreeNodeType::BulletList {
116                            bullet,
117                            bullet_indent,
118                            text_indent,
119                        } = bullet_list.mut_data()
120                        {
121                            // Transform the contained bullet list into a table body...
122                            *bullet_list.mut_data() = TreeNodeType::TBody;
123
124                            // Retrieve the list items from the bullet list...
125                            if let Some(list_items) = bullet_list.mut_children() {
126                                // Iterate over the list items and transform them into table rows
127                                for list_item in list_items {
128                                    if let TreeNodeType::BulletListItem { .. } =
129                                        list_item.mut_data()
130                                    {
131                                        *list_item.mut_data() = TreeNodeType::TRow;
132
133                                        if let Some(list_item_children) = list_item.mut_children() {
134                                            if let Some(nested_child) =
135                                                list_item_children.get_mut(0)
136                                            {
137                                                if let TreeNodeType::BulletList { .. } =
138                                                    nested_child.mut_data()
139                                                {
140                                                    // Remove the list items from nested bullet list and turn them into table cells or entries
141                                                    let mut table_row_cells: Vec<TreeNode> =
142                                                        if let Some(cells) =
143                                                            nested_child.mut_children()
144                                                        {
145                                                            cells.drain(..).collect()
146                                                        } else {
147                                                            panic!("List table row has no cells. Computer says no...")
148                                                        };
149
150                                                    let n_of_entries = table_row_cells.len();
151                                                    for cell in table_row_cells
152                                                        .iter_mut()
153                                                        .take(n_of_entries - 1)
154                                                    {
155                                                        *cell.mut_data() =
156                                                            TreeNodeType::Entry { is_last: false };
157                                                    }
158
159                                                    if let Some(entry) = table_row_cells.last_mut()
160                                                    {
161                                                        *entry.mut_data() =
162                                                            TreeNodeType::Entry { is_last: true };
163                                                    }
164
165                                                    // Remove the bullet list from between table row and table cells...
166                                                    list_item
167                                                        .mut_children()
168                                                        .as_mut()
169                                                        .unwrap()
170                                                        .drain(..);
171                                                    // Insert entries into table row...
172                                                    list_item.append_children(&mut table_row_cells);
173                                                }
174                                            }
175                                        }
176                                    } else if let TreeNodeType::EmptyLine = list_item.mut_data() {
177                                        // Keep as is
178                                    } else {
179                                        eprintln!("Cannot transform anything other than bullet list items or empty lines inside a list table...")
180                                    }
181                                }
182                            }
183                        }
184                    }
185                }
186            }
187            TreeNodeType::Literal { .. } => {}
188            TreeNodeType::LiteralBlock { .. } => {}
189            TreeNodeType::Math { .. } => {}
190            TreeNodeType::MathBlock { .. } => {}
191            TreeNodeType::OptionList { .. } => {}
192            TreeNodeType::OptionListItem { .. } => {}
193            TreeNodeType::OptionString { .. } => {}
194            TreeNodeType::Organization { .. } => {}
195            TreeNodeType::Paragraph { .. } => {}
196            TreeNodeType::ParsedLiteralBlock { .. } => {}
197            TreeNodeType::Pending { .. } => {}
198            TreeNodeType::Problematic { .. } => {}
199            TreeNodeType::Raw { .. } => {}
200            TreeNodeType::Reference { .. } => {}
201            TreeNodeType::Revision { .. } => {}
202            TreeNodeType::Row { .. } => {}
203            TreeNodeType::Rubric { .. } => {}
204            TreeNodeType::Section { .. } => {}
205            TreeNodeType::Sidebar { .. } => {}
206            TreeNodeType::Status { .. } => {}
207            TreeNodeType::StrongEmphasis { .. } => {}
208            TreeNodeType::Subscript { .. } => {}
209            TreeNodeType::SubstitutionDefinition { .. } => {}
210            TreeNodeType::SubstitutionReference { .. } => {}
211            TreeNodeType::Subtitle { .. } => {}
212            TreeNodeType::Superscript { .. } => {}
213            TreeNodeType::SystemMessage { .. } => {}
214            TreeNodeType::Table { .. } => {}
215            TreeNodeType::Target { .. } => {}
216            TreeNodeType::TBody { .. } => {}
217            TreeNodeType::Term { .. } => {}
218            TreeNodeType::Text { .. } => {}
219            TreeNodeType::TGroup { .. } => {}
220            TreeNodeType::THead { .. } => {}
221            TreeNodeType::TRow { .. } => {}
222            TreeNodeType::Title { .. } => {}
223            TreeNodeType::TitleReference { .. } => {}
224            TreeNodeType::Topic { .. } => {}
225            TreeNodeType::Transition {} => {}
226            TreeNodeType::UnknownDirective { .. } => {}
227            TreeNodeType::Version { .. } => {}
228            TreeNodeType::WhiteSpace { .. } => {}
229
230            // ============================
231            //  Sphinx specific directives
232            // ============================
233            TreeNodeType::SphinxOnly { .. } => {}
234            TreeNodeType::SphinxCodeBlock { .. } => {}
235
236            // ========================
237            //  A+ specific directives
238            // ========================
239            TreeNodeType::AplusPOI { .. } => {}
240            TreeNodeType::AplusColBreak => {}
241            TreeNodeType::AplusQuestionnaire { .. } => {}
242            TreeNodeType::AplusPickOne { .. } => {}
243            TreeNodeType::AplusPickAny { .. } => {}
244            TreeNodeType::AplusFreeText { .. } => {}
245            TreeNodeType::AplusPickChoices { .. } => {}
246            TreeNodeType::AplusPickChoice { .. } => {}
247            TreeNodeType::AplusQuestionnaireHints { .. } => {}
248            TreeNodeType::AplusQuestionnaireHint { .. } => {}
249            TreeNodeType::AplusSubmit { .. } => {}
250            TreeNodeType::AplusActiveElementInput { .. } => {}
251            TreeNodeType::AplusActiveElementOutput { .. } => {}
252        };
253
254        if let Some(children) = self.mut_children() {
255            for child in children {
256                child.perform_restructuredtext_transforms()
257            }
258        }
259    }
260}