rustla/doctree/
tree_node_types.rs

1/*!
2A submodule that contains the different tree node types as a single huge enumeration.
3
4Copyright © 2020 Santtu Söderholm
5*/
6use super::*;
7use crate::common::AplusActiveElementClear;
8use crate::common::AplusActiveElementInputType;
9use crate::common::AplusActiveElementOutputType;
10use crate::common::AplusExerciseStatus;
11use crate::common::AplusRadarTokenizer;
12use crate::common::QuizPoints;
13use crate::doctree::directives::AdmonitionType;
14
15
16/// An enumeration of the different possible document node types.
17///
18/// Some of the nodes listed here are redundant. This is because
19/// reStructuredText documentation also [lists](https://docutils.sourceforge.io/docs/ref/doctree.html#element-reference)
20/// nodes that (multiply) inherit from other nodes in the [implementation](https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/docutils/nodes.py),
21/// but Rust has no concept of inheritance built in.
22#[derive(Debug)]
23pub enum TreeNodeType {
24
25    /// The abbreviation element is an inline element used to represent an abbreviation being used in the document. An example of an abbreviation is 'St' being used instead of 'Street'.
26    Abbreviation {
27        name: Option<String>,
28        classes: Option<String>,
29    },
30
31    /// A reference to a web address.
32    AbsoluteURI { text: String },
33
34    /// TODO
35    Acronym,
36
37    /// The address element holds the surface mailing address information for the author (individual or group) of the document, or a third-party contact address. Its structure is identical to that of the literal_block element: whitespace is significant, especially newlines.
38    Address,
39
40    /// Covers all of the standard admonition types of reStructuredText:
41    ///
42    /// 1. attention,
43    /// 2. caution,
44    /// 3. danger,
45    /// 4. error,
46    /// 5. hint,
47    /// 6. important,
48    /// 7. note,
49    /// 8. tip and
50    /// 9. warning,
51    /// 10. admonition
52    ///
53    /// All of these have the same fields, and vary only in how they will be displayed.
54    /// The last variant "admonition" may also contain a title. as one of its fields.
55    Admonition {
56        content_indent: usize,
57        classes: Option<String>,
58        name: Option<String>,
59        variant: AdmonitionType,
60    },
61
62    /// An optional attribution of a `BlockQuote`.
63    /// An attribution is a text block beginning with "--", "---", or a true em-dash,
64    /// flush left within the block quote.
65    /// If the attribution consists of multiple lines,
66    /// the left edges of the second and subsequent lines must align.
67    ///
68    /// If a `BlockQuote` contains an attribution,
69    /// the following node may be a `BlockQuote as well,
70    /// but not otherwise (as it will be interpreted as a part of the previous quote).
71    Attribution {
72        raw_text: String,
73        // parsed_text: Vec<TreeNodeType>
74    },
75
76    /// TODO
77    Author,
78
79    /// TODO
80    Authors,
81
82    /// The "sectnum" (or "section-numbering") directive automatically numbers sections and subsections in a document (if not disabled by the
83    /// --no-section-numbering command line option or the sectnum_xform configuration setting).
84    ///
85    /// Section numbers are of the "multiple enumeration" form, where each level has a number, separated by periods. For example,
86    /// the title of section 1, subsection 2, subsubsection 3 would have "1.2.3" prefixed.
87    ///
88    /// The "sectnum" directive does its work in two passes: the initial parse and a transform. During the initial parse, a "pending" element is
89    /// generated which acts as a placeholder, storing any options internally.
90    /// At a later stage in the processing, the "pending" element triggers a transform, which adds section numbers to titles. Section numbers are
91    /// enclosed in a "generated" element, and titles have their "auto" attribute set to "1".
92    ///
93    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#automatic-section-numbering
94    AutomaticSectionNumbering {
95        depth: Option<u32>,
96        prefix: Option<String>,
97        suffix: Option<String>,
98        start: Option<u32>,
99    },
100
101    /// Text indented relative to previous text,
102    /// without markup indicating the start of
103    /// a list or other container nodes.
104    /// A block quote may end with an `Attribution`,
105    /// which allows placing multiple block quotes
106    /// in a sequence.
107    ///
108    /// Also generated by the `epigraph`, `highlights` and `pull-quote` directives.
109    BlockQuote { body_indent: usize },
110
111    /// An unnumbered list node. These may only contain `BulletListItem` nodes
112    /// or `EmptyLine`s as their direct children.
113    BulletList {
114        bullet: char,
115        bullet_indent: usize,
116        text_indent: usize,
117    },
118
119    /// An unnumbered list item. Can contain any `Body` level elements as its direct children.
120    BulletListItem {
121        bullet: char,
122        bullet_indent: usize,
123        text_indent: usize,
124    },
125
126    /// A `Figure` consists of image data (including image options), an optional *caption* (a single paragraph),
127    /// and an optional legend (arbitrary body elements).
128    /// For page-based output media, figures might float to a different position if this helps the page layout.
129    Caption { indent: usize },
130
131    /// A generic citation target.
132    Citation { body_indent: usize, label: String },
133
134    /// A reference to a bibliographic citation.
135    CitationReference {
136        displayed_text: String,
137        target_label: String,
138    },
139
140    /// A container that triggers the storage of HTML classes
141    /// into the DocTree and gives these to its children, if it has any.
142    Class {
143        body_indent: usize,
144        classes: Vec<String>,
145    },
146
147    /// A classifier for a `DefinitionTerm` in a `DefinitionList`.
148    /// Could be the type of a varible in a function decraration, or something similar.
149    Classifier,
150
151    /// The "code" directive constructs a literal block.
152    /// If the code language is specified, the content is parsed by the Pygments syntax highlighter
153    /// and tokens are stored in nested inline elements with class arguments according to their syntactic category.
154    /// The actual highlighting requires a style-sheet (e.g. one generated by Pygments, see the sandbox/stylesheets
155    /// for examples).
156    ///
157    /// The parsing can be turned off with the syntax_highlight configuration setting and command line option or by
158    /// specifying the language as :class: option instead of directive argument. This also avoids warnings when Pygments
159    /// is not installed or the language is not in the supported languages and markup formats.
160    ///
161    /// For inline code, use the "code" role.
162    ///
163    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#code
164    Code {
165        text: String,
166
167        language: Option<String>,
168        name: Option<String>,
169        class: Option<String>,
170        number_lines: Option<String>,
171    },
172
173    /// TODO
174    ColSpec,
175
176    /// A reStructuredText comment
177    Comment { text: Option<String> },
178
179    /// The "compound" directive is used to create a compound paragraph,
180    /// which is a single logical paragraph containing multiple physical body elements
181    /// such as simple paragraphs,literal blocks, tables, lists, etc.,
182    /// instead of directly containing text and inline elements. For example:
183    ///
184    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#compound-paragraph
185    CompoundParagraph {
186        body_indent: usize,
187
188        name: Option<String>,
189        class: Option<String>,
190    },
191
192    /// TODO
193    Contact,
194
195    /// The "container" directive surrounds its contents (arbitrary body elements) with a generic block-level "container" element.
196    /// Combined with the optional "classes" attribute argument(s), this is an extension mechanism for users & applications.
197    /// The "container" directive is the equivalent of HTML's <div> element. It may be used to group a sequence of elements for user-
198    /// or application-specific purposes.
199    ///
200    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#container
201    Container {
202        body_indent: usize,
203
204        class_names: Option<Vec<String>>,
205        name: Option<String>,
206    },
207
208    /// TODO
209    Copyright,
210
211    /// The "csv-table" directive is used to create a table from CSV (comma-separated values) data. CSV is
212    /// a common data format generated by spreadsheet applications and commercial databases.
213    /// The data may be internal (an integral part of the document) or external (a separate file).
214    ///
215    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#id4
216    CSVTable {
217        name: Option<String>,
218        class: Option<String>,
219        widths: Option<TableColWidths>,
220        width: Option<MetricType>,
221        header_rows: Option<u32>,
222        stub_columns: Option<u32>,
223        header: Option<Vec<String>>,
224        file: Option<String>,
225        url: Option<String>,
226        encoding: Option<String>,
227        delim: Option<char>,
228        quote: Option<char>,
229        keepspace: Option<bool>,
230        escape: Option<char>,
231        align: Option<HorizontalAlignment>,
232    },
233
234    /// Document metadata
235    Date,
236
237    /// ?
238    Decoration,
239
240    /// The definition of a definition list.
241    Definition,
242
243    /// A list of definitions. Contains `DefinitionListItems` or `EmptyLine` nodes
244    /// as its direct children.
245    DefinitionList { term_indent: usize },
246
247    /// A child node type of `DefinitionList`.
248    /// Contains a map of `DefinitionTerm`s and the corresponding
249    /// `TermDefinitions`, in addition to optional term classifiers.
250    DefinitionListItem {
251        term: String,
252        classifiers: Vec<String>,
253        body_indent: usize,
254    },
255
256    /// ?
257    Description,
258
259    /// ?
260    DocInfo,
261
262    /// These are interactive Python sessions contained in Python docstrings.
263    /// Based on the Python standard library [doctest](http://www.python.org/doc/current/lib/module-doctest.html) module.
264    ///
265    /// Doctest blocks begin with ">>>", the python REPL main prompt and end with a blank line.
266    /// They are a special case of the literal block and if both are present,
267    /// the literal block takes precedence.
268    DoctestBlock,
269
270    /// The root node of an reStructuredText document tree.
271    Document,
272
273    /// Emphasised or italicized text.
274    Emphasis { text: String },
275
276    /// A simple empty line, that contains no actual data.
277    /// These can be contained in pretty much any container
278    /// node, such as lists or list items, in addition to
279    /// existing between body level elements.
280    EmptyLine,
281
282    /// Table data cells or entries may contain arbitrary body elements.
283    Entry {
284        // Whether this node is the last element in its container row.
285        is_last: bool,
286    },
287
288    /// An enumerated list node. Can only contain `EnumeratedListItem` and `EmptyLine`
289    /// nodes as its direct children.
290    EnumeratedList {
291        delims: EnumDelims,
292        kind: EnumKind,
293        start_index: usize,
294        n_of_items: usize,
295        enumerator_indent: usize,
296    },
297
298    /// Child node type of `EnumeratedList`. Can contain any `Body`elements
299    /// as its children.
300    EnumeratedListItem {
301        delims: EnumDelims,
302        kind: EnumKind,
303        index_in_list: usize,
304        enumerator_indent: usize,
305        text_indent: usize,
306    },
307
308    /// A target for an external hyperlink.
309    /// Contains a URI pointing  to an external resource
310    ExternalHyperlinkTarget {
311        marker_indent: usize,
312        target: String,
313        uri: String,
314    },
315
316    /// A field of a field list
317    Field,
318
319    /// The parameter that `FieldName` refers to. May contain arbitrary body elements,
320    /// just like bulleted and enumerated list items. The first line after the marker specifies
321    /// the indentation used as a reference for parsing the rest of the block.
322    FieldBody { indentation: usize },
323
324    /// A list of fields, that are used as a part of the
325    /// reStructuredText extension syntax, such as directives.
326    /// Bibliographies are a special case of these types of lists.
327    FieldList { marker_indent: usize },
328
329    /// A field item of a `FieldList`. Consists of a marker with a field name and a
330    /// field body consisting of arbitrary body elements.
331    /// ```text
332    /// +--------------------+----------------------+
333    /// | ":" field name ":" | field body           |
334    /// +-------+------------+                      |
335    ///         | (body elements)+                  |
336    ///         +-----------------------------------+
337    /// ```
338    FieldListItem {
339        raw_marker_name: String,
340        marker_name_as_inline_nodes: Vec<TreeNodeType>,
341        marker_indent: usize,
342        body_indent: usize,
343    },
344
345    /// A "figure" consists of image data (including image options),
346    /// an optional caption (a single paragraph), and an optional legend (arbitrary body elements).
347    /// For page-based output media, figures might float to a different position if this helps the page layout.
348    Figure {
349        /// The indentation of the caption and legend of this `Figure`.
350        body_indent: usize,
351
352        // Options
353        align: Option<HorizontalAlignment>, // not passed to contained image
354        figwidth: Option<Length>,
355        figclass: Option<String>,
356        name: Option<String>,
357    },
358
359    /// The "header" and "footer" directives create document decorations, useful for page navigation, notes, time/datestamp, etc.
360    ///
361    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#document-header-footer
362    Footer { body_indent: usize },
363
364    /// A foonote citation target. Contains a label and the foornote text itself.
365    ///
366    /// The "target-notes" directive creates a footnote for each external target in the text,
367    /// and corresponding footnote references after each reference. For every explicit target (of the form, .. _target name: URL) in the text,
368    /// a footnote will be generated containing the visible URL as content.
369    ///
370    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#target-footnotes
371    Footnote {
372        body_indent: usize,
373        kind: FootnoteKind,
374        label: String,  // Displayed label
375        target: String, // Reference target
376    },
377
378    /// A reference to a foot note.
379    FootnoteReference {
380        displayed_text: String,
381        target_label: String,
382        kind: FootnoteKind
383    },
384
385    /// ?
386    Generated,
387
388    /// The "header" and "footer" directives create document decorations, useful for page navigation, notes, time/datestamp, etc.
389    ///
390    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#document-header-footer
391    Header { body_indent: usize },
392
393    /// An image without a surrounding figure node. Can be inserted inline, as well
394    /// (as soon asn substitution definitions and references get implemented...).
395    Image {
396        uri: String,
397        // Options
398        alt: Option<String>,
399        height: Option<Length>,
400        width: Option<Length>,
401        scale: Option<f64>,
402        align: Option<HTMLAlignment>,
403        target: Option<String>,
404        name: Option<String>,
405        class: Option<String>,
406        /// Images can be inserted inline via substitution references
407        /// (not yet implemented in ruSTLa).
408        inline: bool
409    },
410
411    Include {
412        uri: String,
413        // Options
414        start_line: Option<u32>,
415        end_line: Option<u32>,
416        start_after: Option<u32>,
417        end_before: Option<u32>,
418        literal: bool,
419        code: Option<Option<String>>,
420        /// This might be set or not, and if it is, it might contain a start line number or not.
421        number_lines: Option<Option<u32>>,
422        encoding: Option<String>,
423        tab_width: Option<u32>,
424        name: Option<String>,
425        class: Option<String>
426    },
427
428    /// An indirect hyperlink target. Contains a hyperlink reference pointing
429    /// to an internal or and external hyperlink.
430    IndirectHyperlinkTarget {
431        marker_indent: usize,
432        target: String,
433        indirect_target: String,
434    },
435
436    /// ?
437    Inline,
438
439    /// An inline reference target.
440    InlineTarget { target_label: String },
441
442    /// This node type is reserved for unknown interpreted text roles.
443    InterpretedText {
444        role: String,
445        content: String
446    },
447
448    /// ?
449    Label,
450
451    /// A `Figure` consists of image data (including image options), an optional caption (a single paragraph),
452    /// and an optional *legend* (arbitrary body elements).
453    /// For page-based output media, figures might float to a different position if this helps the page layout.
454    Legend { body_indent: usize },
455
456    /// A line of a line block.
457    Line,
458
459    /// A block of text where each new line begins with an unindented '|',
460    /// followed be text with specific left-alignment, used as a reference
461    /// for the rest of the block.
462    /// Allows writing blocks of text, where the struture of the lines
463    /// is meaningful, such as poetry.
464    ///
465    /// The symbols '|' may be omitted, as they signify the start of a new
466    /// line in the rendered output.
467    /// ```txt
468    /// +------+-----------------------+
469    /// | "| " | line                  |
470    /// +------| continuation line     |
471    ///        +-----------------------+
472    /// ```
473    LineBlock,
474
475    /// The "list-table" directive is used to create a table from data in a uniform two-level bullet list.
476    /// "Uniform" means that each sublist (second-level list) must contain the same number of list items.
477    ///
478    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#list-table
479    ListTable {
480        body_indent: usize,
481
482        /// An optional title, given as the directive argument.
483        title: Option<String>,
484        /// A comma- or space-separated list of relative column widths. The default is equal-width columns (100%/#columns).
485        /// The special value "auto" may be used by writers to decide whether to delegate the determination of column widths to the backend (LaTeX, the HTML browser, ...).
486        widths: Option<TableColWidths>,
487        /// Forces the width of the table to the specified length or percentage of the line width. If omitted, the renderer determines the width of the table based on its contents.
488        width: Option<MetricType>,
489        /// The number of rows of list data to use in the table header. Defaults to 0.
490        header_rows: Option<u32>,
491        /// The number of table columns to use as stubs (row titles, on the left). Defaults to 0.
492        stub_columns: Option<u32>,
493        /// The horizontal alignment of the table. (New in Docutils 0.13)
494        align: Option<HorizontalAlignment>,
495    },
496
497    /// Literal text, usually reserved for code.
498    Literal { text: String },
499
500    /// Paragraph (possibly empty) ending in a "::" signifies the start of a literal block of text.
501    /// Text contained in a literal block is not interpreted in any way,
502    /// but simply stored in this node as is.
503    LiteralBlock { text: String },
504
505    /// The "math" directive inserts blocks with mathematical content (display formulas, equations)
506    /// into the document. The input format is subset of LaTeX math syntax with support for Unicode symbols.
507    /// For inline formulas, use the "math" role.
508    ///
509    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#math
510    Math {
511        text: String,
512        name: Option<String>,
513        class: Option<String>,
514    },
515
516    /// A node for display-style mathematics (LaTeX).
517    MathBlock {
518        math_block: String,
519
520        name: Option<String>,
521        class: Option<String>,
522    },
523
524    /// A two-column list of command line options, such as the ones typically seen on unix `man` pages.
525    /// Four types of options are supported:
526    ///
527    /// 1. short POSIX options with one '-' and an opion letter,
528    /// 2. Long POSIX options with "--", followed by an option word.
529    ///    Some systems might use a single dash.
530    /// 3. Old GNU-style options starting with a '+', followed by an option letter (!!!deprecated!!!)
531    /// 4. DOS/VMS options starting with a '/', followed by an option letter or a word.
532    ///
533    /// The recognized syntax is based on Python's `getopt.py` module.
534    OptionList { option_indent: usize },
535
536    /// A single option in an `OptionList`. Consists of an option,
537    /// folllowed by and optional argument and a description.
538    /// May contain arbitrary indented body elements after these:
539    /// ```text
540    /// +----------------------------+-------------+
541    /// | option [" " argument] "  " | description |
542    /// +-------+--------------------+             |
543    ///         | (body elements)+                 |
544    ///         +----------------------------------+
545    /// ```
546    OptionListItem { body_indent: usize },
547
548    /// ?
549    OptionString,
550
551    /// Document metadata
552    Organization,
553
554    /// A node constructed of a left-aligned block of text
555    /// with no special starter markers.
556    Paragraph { indent: usize },
557
558    ParsedLiteralBlock,
559
560    Pending,
561
562    Problematic,
563
564    Raw,
565
566    /// A general reference to a reference target.
567    Reference {
568        displayed_text: Option<String>,
569        reference: crate::common::Reference,
570    },
571
572    Revision,
573
574    Row,
575
576    /// The "rubric" directive inserts a "rubric" element into the document tree. A rubric is like an informal
577    /// heading that doesn't correspond to the document's structure.
578    ///
579    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#rubric
580    Rubric {
581        name: Option<String>,
582        class: Option<String>,
583    },
584
585    /// A section title node, that contains the title text,
586    /// in addition to its marker type and (sub)section level.
587    Section {
588        title_text: String,
589        level: usize,
590        line_style: SectionLineStyle,
591    },
592
593    /// Sidebars are like miniature, parallel documents that occur inside other documents, providing related or reference material.
594    /// A sidebar is typically offset by a border and "floats" to the side of the page; the document's main text may flow around it.
595    /// Sidebars can also be likened to super-footnotes; their content is outside of the flow of the document's main text.
596    ///
597    /// The sidebar element is a nonrecursive section-like construct which may occur at the top level of a section wherever a body element
598    /// (list, table, etc.) is allowed. In other words, sidebar elements cannot nest inside body elements, so you can't have a sidebar inside
599    /// a table or a list, or inside another sidebar (or topic).
600    Sidebar { body_indent: usize },
601
602    Status,
603
604    /// Strongly emphasised text, usually rendered in bold.
605    StrongEmphasis { text: String },
606
607    /// As the name impies, generates inline subscripted text.
608    Subscript { text: String },
609
610    /// Explicit markup node, as in begins with ".. " followed by a vertical bar '|',
611    /// substitution text and another '|'. The text may not begin or end with whitespace.
612    /// Substitution definition blocks may contain a nested, *inline compatible* directive
613    /// *without* the leading ".. ", such as `image` or `replace`.
614    /// ```text
615    /// +-------+-----------------------------------------------------+
616    /// | ".. " | "|" substitution text "| " directive type "::" data |
617    /// +-------+ directive block                                     |
618    ///         |                                                     |
619    ///         +-----------------------------------------------------+
620    /// ```
621    SubstitutionDefinition,
622
623    /// A reference that is to be substituted with the reference target directive output.
624    SubstitutionReference {
625        substitution_label: String,
626        // displayed_text: Option<String>,
627        target_label: Option<String>,
628    },
629
630    /// Document metadata
631    Subtitle,
632
633    /// Inline superscripted text.
634    Superscript { text: String },
635
636    /// An error node (currently unused).
637    SystemMessage,
638
639    /// The "table" directive is used to associate a title with a table or specify options.
640    ///
641    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#table
642    Table {
643        name: Option<String>,
644        class: Option<String>,
645        align: Option<HorizontalAlignment>,
646        widths: Option<Vec<usize>>,
647        width: Option<Length>,
648    },
649
650    Target,
651    /// A table body node
652    TBody,
653
654    Term,
655
656    /// A plain text node, that contains no special markup.
657    Text { text: String },
658
659    /// Specifies atable group
660    TGroup,
661
662    /// Specifies a table header.
663    THead,
664
665    /// Specifies a table row.
666    TRow,
667
668    /// Document metadata.
669    Title,
670
671    /// A reference to a title.
672    TitleReference {
673        displayed_text: String,
674        target_label: String,
675    },
676
677    /// The topic element is a nonrecursive section-like construct which may occur at the top level of a section wherever a body element (list, table, etc.) is allowed.
678    /// In other words, topic elements cannot nest inside body elements, so you can't have a topic inside a table or a list, or inside another topic.
679    /// Topics may contain only body elements.
680    ///
681    /// The "contents" directive generates a table of contents (TOC) in a topic.
682    /// Topics, and therefore tables of contents, may occur anywhere a section or transition may occur.
683    /// Body elements and topics may not contain tables of contents.
684    ///
685    /// Details: https://docutils.sourceforge.io/docs/ref/rst/directives.html#table-of-contents
686    Topic {
687        title: String,
688        depth: Option<u32>,
689        local: Option<bool>,
690        backlinks: Option<ToCBacklinks>,
691        class: Option<String>,
692    },
693
694    /// A node corresponding to LaTeX's `\hrulefill` command.
695    Transition,
696
697    UnknownDirective {
698        directive_name: String,
699        argument: String,
700        options: std::collections::HashMap<String, String>,
701        body_indent: usize,
702    },
703
704    /// Document metadata
705    Version,
706
707    /// Generic inline whitespace that covers everything from spaces to newlines.
708    WhiteSpace { text: String },
709
710    // ============================
711    //  Sphinx specific directives
712    // ============================
713    SphinxOnly {
714        expression: String,
715        body_indent: usize,
716    },
717
718    /// A Sphinx-specific code block. See https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-code-block
719    /// for details.
720    SphinxCodeBlock {
721        language: String,
722        linenos: bool,
723        lineno_start: Option<usize>,
724        emphasize_lines: Option<Vec<usize>>,
725        caption: Option<String>,
726        name: Option<String>,
727        dedent: Option<usize>,
728        force: bool,
729        code_text: String,
730    },
731
732    // ========================
733    //  A+ specific directives
734    // ========================
735
736    /// A "point of interest" summary block.
737    /// A point of interest is mostly like a normal admonition
738    /// ("coloured info box"), but they are also linked to each other
739    /// with next/previous links. The links enable the user to quickly
740    /// navigate between the points of interest.
741    AplusPOI {
742        title: String,
743
744        // Information needed by the parser
745        body_indent: usize,
746
747        // Options
748        id: Option<String>,
749        previous: Option<String>,
750        next: Option<String>,
751        hidden: Option<String>,
752        class: Option<String>,
753        height: Option<Length>,
754        columns: Option<String>,
755        bgimg: Option<String>,
756        not_in_slides: Option<String>,
757        not_in_book: Option<String>,
758        no_poi_box: Option<String>,
759    },
760
761    /// A node that can be inserted inside A+ directives that support multiple columns.
762    /// Placing a line that conforms to he regex `[ ]+::newcol` with the `::newcol` having proper indentation
763    /// with respect to the multicol directive will generate this type of node.
764    AplusColBreak,
765
766    /// A quiz node that corresponds to the questionnaire A+ directive.
767    AplusQuestionnaire {
768        // Required by the parser
769        body_indent: usize,
770        points_from_children: QuizPoints,
771
772        // Directive arguments
773        key: String,
774        max_points: Option<QuizPoints>,
775        difficulty: Option<String>,
776
777        // Directive options
778        // source: https://github.com/apluslms/a-plus-rst-tools#1-graded-questionnaire
779        submissions: Option<String>,
780        points_to_pass: Option<String>,
781        feedback: Option<String>,
782        title: Option<String>,
783        no_override: Option<String>,
784        pick_randomly: Option<String>,
785        preserve_questions_between_attempts: Option<String>,
786        category: Option<String>,
787        status: Option<String>,
788        reveal_model_at_max_submissions: Option<String>,
789        show_model: Option<String>,
790        allow_assistant_viewing: Option<String>,
791        allow_assistant_grading: Option<String>,
792    },
793
794    /// See the documentation for the `quoestionnaire` directive:
795    /// https://github.com/apluslms/a-plus-rst-tools#1-graded-questionnaire
796    AplusPickOne {
797        // Needed by the parser
798        body_indent: usize,
799
800        points: QuizPoints,
801        class: Option<String>,
802        required: bool,
803        key: Option<String>,
804        dropdown: bool,
805    },
806
807    /// See the documentation for the `quoestionnaire` directive:
808    /// https://github.com/apluslms/a-plus-rst-tools#1-graded-questionnaire
809    AplusPickAny {
810        // Needed by the parser
811        body_indent: usize,
812
813        points: QuizPoints,
814        class: Option<String>,
815        required: bool,
816        key: Option<String>,
817        partial_points: bool,
818        randomized: bool,
819        correct_count: Option<u32>,
820        preserve_questions_between_attempts: bool,
821    },
822
823    /// See the documentation for the `quoestionnaire` directive:
824    /// https://github.com/apluslms/a-plus-rst-tools#1-graded-questionnaire
825    AplusFreeText {
826        // Needed by the parser
827        body_indent: usize,
828
829        // Directive arguments
830        points: QuizPoints,
831
832        /// One of `int`, `float`, `string`, `subdiff`, `regexp`, `unsortedchars`,
833        /// with `string` and `regexp` having the `-`-separated modifiers
834        /// , `ignorews`, `ignorequotes`, `requirecase`, `ignorerepl` and `ignoreparenthesis` available.
835        compare_method: String,
836
837        model_answer: String,
838
839        // Directive options
840        class: Option<String>,
841        required: Option<String>,
842        key: Option<String>,
843        length: Option<String>,
844        height: Option<String>,
845    },
846
847    /// A node that contains the choices of an A+ `pick` type question.
848    AplusPickChoices { body_indent: usize },
849
850    /// A single answer choice inside an A+ pick-(one|any) question.
851    AplusPickChoice {
852        label: String,
853        is_correct: bool,
854        is_pre_selected: bool,
855        is_neutral: bool, // Only set with pick-any nodes
856    },
857
858    /// A list type node for containing `AplusQuestionnaireHint`s.
859    AplusQuestionnaireHints { body_indent: usize },
860
861    /// A hint for questionnaire pick-{one, any} and freetext questions.
862    AplusQuestionnaireHint {
863        label: String,
864        show_when_not_selected: bool,
865        question_type: crate::common::AplusQuestionnaireType,
866    },
867
868    /// A+ submit-type exercise. See https://github.com/apluslms/a-plus-rst-tools#3-submittable-exercise.
869    AplusSubmit {
870        body_indent: usize,
871        key: String,
872        difficulty: String,
873        max_points: QuizPoints,
874
875        config: String,
876        submissions: u32,
877        points_to_pass: QuizPoints,
878        class: String,
879        title: String,
880        category: String, // Default: submit
881        status: AplusExerciseStatus,
882        ajax: bool,
883        allow_assistant_viewing: bool,
884        allow_assistant_grading: bool,
885        quiz: bool,
886        url: String,
887        radar_tokenizer: AplusRadarTokenizer,
888        radar_minimum_match_tokens: Option<u32>,
889        lti: String,
890        lti_resource_link_id: String,
891        lti_open_in_iframe: bool,
892        lti_aplus_get_and_post: bool,
893    },
894
895    AplusActiveElementInput {
896        key_for_input: String,
897        title: Option<String>,
898        default: Option<String>,
899        class: Option<String>,
900        width: Option<Length>,
901        height: Option<Length>,
902        clear: Option<AplusActiveElementClear>,
903        input_type: Option<AplusActiveElementInputType>,
904        file: Option<String>,
905    },
906
907    AplusActiveElementOutput {
908        key_for_output: String,
909        config: String,
910        inputs: String,
911        title: Option<String>,
912        class: Option<String>,
913        width: Option<Length>,
914        height: Option<Length>,
915        clear: Option<AplusActiveElementClear>,
916        output_type: AplusActiveElementOutputType,
917        submissions: Option<u32>,
918        scale_size: bool,
919        status: AplusExerciseStatus,
920    },
921}
922
923use crate::doctree::node_categories::*;
924
925impl TreeNodeType {
926
927    /// Returns the relevant content indent of each node type.
928    /// This is useful, when one is trying to find out whether a node belongs to a parent node.
929    /// Node containerzation is determined by indentation in reStructuredText.
930    pub fn body_indent(&self) -> Option<usize> {
931        match self {
932            Self::Abbreviation { .. } => None,
933            Self::AbsoluteURI { .. } => None,
934            Self::Acronym { .. } => None,
935            Self::Address => None,
936            Self::Admonition { content_indent, .. } => Some(*content_indent),
937            Self::Attribution { .. } => None,
938            Self::Author { .. } => None,
939            Self::Authors { .. } => None,
940            Self::AutomaticSectionNumbering { .. } => None,
941            Self::BlockQuote { body_indent, .. } => Some(*body_indent),
942            Self::BulletList { bullet_indent, .. } => Some(*bullet_indent),
943            Self::BulletListItem { text_indent, .. } => Some(*text_indent),
944            Self::Caption { .. } => None,
945            Self::Citation { body_indent, .. } => Some(*body_indent),
946            Self::CitationReference { .. } => None,
947            Self::Class { body_indent, .. } => Some(*body_indent),
948            Self::Classifier { .. } => None,
949            Self::Code { .. } => None,
950            Self::ColSpec { .. } => None,
951            Self::Comment { .. } => None,
952            Self::CompoundParagraph { body_indent, .. } => Some(*body_indent),
953            Self::Contact { .. } => None,
954            Self::Container { body_indent, .. } => Some(*body_indent),
955            Self::Copyright { .. } => None,
956            Self::CSVTable { .. } => None,
957            Self::Date => None,
958            Self::Decoration => None,
959            Self::Definition => None,
960            Self::DefinitionList { term_indent, .. } => Some(*term_indent),
961            Self::DefinitionListItem { body_indent, .. } => Some(*body_indent),
962            Self::Description => None,
963            Self::DocInfo => None,
964            Self::DoctestBlock { .. } => None,
965            Self::Document { .. } => Some(0),
966            Self::Emphasis { .. } => None,
967            Self::EmptyLine => None,
968            Self::Entry { .. } => None,
969            Self::EnumeratedList {
970                enumerator_indent, ..
971            } => Some(*enumerator_indent),
972            Self::EnumeratedListItem { text_indent, .. } => Some(*text_indent),
973            Self::ExternalHyperlinkTarget { .. } => None,
974            Self::Field => None,
975            Self::FieldBody { .. } => None,
976            Self::FieldList { marker_indent, .. } => Some(*marker_indent),
977            Self::FieldListItem { body_indent, .. } => Some(*body_indent),
978            Self::Figure { body_indent, .. } => Some(*body_indent),
979            Self::Footer { body_indent, .. } => Some(*body_indent),
980            Self::Footnote { body_indent, .. } => Some(*body_indent),
981            Self::FootnoteReference { .. } => None,
982            Self::Header { body_indent, .. } => Some(*body_indent),
983            Self::Generated => None,
984            Self::Image { .. } => None,
985            Self::Include { .. } => None,
986            Self::IndirectHyperlinkTarget { .. } => None,
987            Self::Inline { .. } => None,
988            Self::InlineTarget { .. } => None,
989            Self::InterpretedText { .. } => None,
990            Self::Label { .. } => None,
991            Self::Legend { body_indent, .. } => Some(*body_indent),
992            Self::Line { .. } => None,
993            Self::LineBlock { .. } => None,
994            Self::ListTable { body_indent, .. } => Some(*body_indent),
995            Self::Literal { .. } => None,
996            Self::LiteralBlock { .. } => None,
997            Self::Math { .. } => None,
998            Self::MathBlock { .. } => None,
999            Self::OptionList { option_indent, .. } => Some(*option_indent),
1000            Self::OptionListItem { body_indent, .. } => Some(*body_indent),
1001            Self::OptionString { .. } => None,
1002            Self::Organization { .. } => None,
1003            Self::Paragraph { indent, .. } => Some(*indent),
1004            Self::ParsedLiteralBlock { .. } => None,
1005            Self::Pending { .. } => None,
1006            Self::Problematic { .. } => None,
1007            Self::Raw { .. } => None,
1008            Self::Reference { .. } => None,
1009            Self::Revision { .. } => None,
1010            Self::Row { .. } => None,
1011            Self::Rubric { .. } => None,
1012            Self::Section { .. } => Some(0),
1013            Self::Sidebar { body_indent, .. } => Some(*body_indent),
1014            Self::Status { .. } => None,
1015            Self::StrongEmphasis { .. } => None,
1016            Self::Subscript { .. } => None,
1017            Self::SubstitutionDefinition { .. } => None,
1018            Self::SubstitutionReference { .. } => None,
1019            Self::Subtitle { .. } => None,
1020            Self::Superscript { .. } => None,
1021            Self::SystemMessage { .. } => None,
1022            Self::Table { .. } => None,
1023            Self::Target { .. } => None,
1024            Self::TBody { .. } => None,
1025            Self::Term { .. } => None,
1026            Self::Text { .. } => None,
1027            Self::TGroup { .. } => None,
1028            Self::THead { .. } => None,
1029            Self::TRow { .. } => None,
1030            Self::Title { .. } => None,
1031            Self::TitleReference { .. } => None,
1032            Self::Topic { .. } => None,
1033            Self::Transition => None,
1034            Self::UnknownDirective { body_indent, .. } => Some(*body_indent),
1035            Self::Version { .. } => None,
1036            Self::WhiteSpace { .. } => None,
1037
1038            // ========================
1039            //  Sphinx specific directives
1040            // ========================
1041            Self::SphinxOnly { body_indent, .. } => Some(*body_indent),
1042            Self::SphinxCodeBlock { .. } => None,
1043
1044            // ========================
1045            //  A+ specific directives
1046            // ========================
1047            Self::AplusPOI { body_indent, .. } => Some(*body_indent),
1048            Self::AplusColBreak => None,
1049            Self::AplusQuestionnaire { body_indent, .. } => Some(*body_indent),
1050            Self::AplusPickOne { body_indent, .. } => Some(*body_indent),
1051            Self::AplusPickAny { body_indent, .. } => Some(*body_indent),
1052            Self::AplusFreeText { body_indent, .. } => Some(*body_indent),
1053            Self::AplusPickChoices { body_indent, .. } => Some(*body_indent),
1054            Self::AplusPickChoice { .. } => None,
1055            Self::AplusQuestionnaireHints { body_indent } => Some(*body_indent),
1056            Self::AplusQuestionnaireHint { .. } => None,
1057            Self::AplusSubmit { body_indent, .. } => Some(*body_indent),
1058            Self::AplusActiveElementInput { .. } => None,
1059            Self::AplusActiveElementOutput { .. } => None,
1060        }
1061    }
1062
1063    /// According to the [reStructuredText DTD](https://docutils.sourceforge.io/docs/ref/doctree.html)
1064    /// each node type is associated with a set of categories.
1065    /// This function returns that set (an immutable iterator) for each defined node type.
1066    pub fn node_categories(&self) -> impl Iterator<Item = &NodeCategory> {
1067        let categories: &[NodeCategory] = match self {
1068            Self::Abbreviation { .. } => &ABBREVIATION_CATEGORIES,
1069            Self::AbsoluteURI { .. } => &ABSOLUTE_URI_CATEGORIES,
1070            Self::Acronym { .. } => &ACRONYM_CATEGORIES,
1071            Self::Address => &ADDRESS_CATEGORIES,
1072            Self::Admonition { .. } => &ADMONITION_CATEGORIES,
1073            Self::Attribution { .. } => &ATTRIBUTION_CATEGORIES,
1074            Self::Author { .. } => &AUTHOR_CATEGORIES,
1075            Self::Authors { .. } => &AUTHORS_CATEGORIES,
1076            Self::AutomaticSectionNumbering { .. } => &AUTO_SECTION_NUMBERING_CATEGORIES,
1077            Self::BlockQuote { .. } => &BLOCK_QUOTE_CATEGORIES,
1078            Self::BulletList { .. } => &BULLET_LIST_CATEGORIES,
1079            Self::BulletListItem { .. } => &BULLET_LIST_ITEM_CATEGORIES,
1080            Self::Caption { .. } => &CAPTION_CATEGORIES,
1081            Self::Citation { .. } => &CITATION_CATEGORIES,
1082            Self::CitationReference { .. } => &CITATION_REFERENCE_CATEGORIES,
1083            Self::Class { .. } => &CLASS_CATEGORIES,
1084            Self::Classifier { .. } => &CLASSIFIER_CATEGORIES,
1085            Self::Code { .. } => &CODE_CATEGORIES,
1086            Self::ColSpec { .. } => &COLSPEC_CATEGORIES,
1087            Self::Comment { .. } => &COMMENT_CATEGORIES,
1088            Self::CompoundParagraph { .. } => &COMPOUND_PARAGRAPH_CATEGORIES,
1089            Self::Contact { .. } => &CONTACT_CATEGORIES,
1090            Self::Container { .. } => &CONTAINER_CATEGORIES,
1091            Self::Copyright { .. } => &COPYRIGHT_CATEGORIES,
1092            Self::CSVTable { .. } => &CSV_TABLE_CATEGORIES,
1093            Self::Date => &DATE_CATEGORIES,
1094            Self::Decoration => &DECORATION_CATEGORIES,
1095            Self::Definition => &DEFINITION_CATEGORIES,
1096            Self::DefinitionList { .. } => &DEFINITION_LIST_CATEGORIES,
1097            Self::DefinitionListItem { .. } => &DEFINITION_LIST_ITEM_CATEGORIES,
1098            Self::Description => &DESCRIPTION_CATEGORIES,
1099            Self::DocInfo => &DOC_INFO_CATEGORIES,
1100            Self::DoctestBlock { .. } => &DOCTEST_BLOCK_CATEGORIES,
1101            Self::Document { .. } => &DOCUMENT_CATEGORIES,
1102            Self::Emphasis { .. } => &EMPHASIS_CATEGORIES,
1103            Self::EmptyLine => &EMPTY_LINE_CATEGORIES,
1104            Self::Entry { .. } => &ENTRY_CATEGORIES,
1105            Self::EnumeratedList { .. } => &ENUMERATED_LIST_CATEGORIES,
1106            Self::EnumeratedListItem { .. } => &ENUMERATED_LIST_ITEM_CATEGORIES,
1107            Self::ExternalHyperlinkTarget { .. } => &EXTERNAL_HYPERLINK_TARGET_CATEGORIES,
1108            Self::Field => &FIELD_CATEGORIES,
1109            Self::FieldBody { .. } => &FIELD_BODY_CATEGORIES,
1110            Self::FieldList { .. } => &FIELD_LIST_CATEGORIES,
1111            Self::FieldListItem { .. } => &FIELD_LIST_ITEM_CATEGORIES,
1112            Self::Figure { .. } => &FIGURE_CATEGORIES,
1113            Self::Footer { .. } => &FOOTER_CATEGORIES,
1114            Self::Footnote { .. } => &FOOTNOTE_CATEGORIES,
1115            Self::FootnoteReference { .. } => &FOOTNOTE_REFERENCE_CATEGORIES,
1116            Self::Header { .. } => &HEADER_CATEGORIES,
1117            Self::Generated => &GENERATED_CATEGORIES,
1118            Self::Image { .. } => &IMAGE_CATEGORIES,
1119            Self::Include { .. } => &INCLUDE_CATEGORIES,
1120            Self::IndirectHyperlinkTarget { .. } => &INDIRECT_HYPERLINK_TARGET_CATEGORIES,
1121            Self::Inline { .. } => &INLINE_CATEGORIES,
1122            Self::InlineTarget { .. } => &INLINE_TARGET_CATEGORIES,
1123            Self::InterpretedText { .. } => &INTERPRETED_TEXT_CATEGORIES,
1124            Self::Label { .. } => &LABEL_CATEGORIES,
1125            Self::Legend { .. } => &LEGEND_CATEGORIES,
1126            Self::Line { .. } => &LINE_CATEGORIES,
1127            Self::LineBlock { .. } => &LINE_BLOCK_CATEGORIES,
1128            Self::ListTable { .. } => &LIST_TABLE_CATEGORIES,
1129            Self::Literal { .. } => &LITERAL_CATEGORIES,
1130            Self::LiteralBlock { .. } => &LITERAL_BLOCK_CATEGORIES,
1131            Self::Math { .. } => &MATH_CATEGORIES,
1132            Self::MathBlock { .. } => &MATH_BLOCK_CATEGORIES,
1133            Self::OptionList { .. } => &OPTION_LIST_CATEGORIES,
1134            Self::OptionListItem { .. } => &OPTION_LIST_ITEM_CATEGORIES,
1135            Self::OptionString { .. } => &OPTION_STRING_CATEGORIES,
1136            Self::Organization { .. } => &ORGANIZATION_CATEGORIES,
1137            Self::Paragraph { .. } => &PARAGRAPH_CATEGORIES,
1138            Self::ParsedLiteralBlock { .. } => &PARSED_LITERAL_BLOCK_CATEGORIES,
1139            Self::Pending { .. } => &PENDING_CATEGORIES,
1140            Self::Problematic { .. } => &PROBLEMATIC_CATEGORIES,
1141            Self::Raw { .. } => &RAW_CATEGORIES,
1142            Self::Reference { .. } => &REFERENCE_CATEGORIES,
1143            Self::Revision { .. } => &REVISION_CATEGORIES,
1144            Self::Row { .. } => &ROW_CATEGORIES,
1145            Self::Rubric { .. } => &RUBRIC_CATEGORIES,
1146            Self::Section { .. } => &SECTION_CATEGORIES,
1147            Self::Sidebar { .. } => &SIDEBAR_CATEGORIES,
1148            Self::Status { .. } => &STATUS_CATEGORIES,
1149            Self::StrongEmphasis { .. } => &STRONG_EMPHASIS_CATEGORIES,
1150            Self::Subscript { .. } => &SUBSCRIPT_CATEGORIES,
1151            Self::SubstitutionDefinition { .. } => &SUBSTITUTION_DEF_CATEGORIES,
1152            Self::SubstitutionReference { .. } => &SUBSTITUTION_REF_CATEGORIES,
1153            Self::Subtitle { .. } => &SUBTITLE_CATEGORIES,
1154            Self::Superscript { .. } => &SUPERSCRIPT_CATEGORIES,
1155            Self::SystemMessage { .. } => &SYSTEM_MESSAGE_CATEGORIES,
1156            Self::Table { .. } => &TABLE_CATEGORIES,
1157            Self::Target { .. } => &TARGET_CATEGORIES,
1158            Self::TBody { .. } => &T_BODY_CATEGORIES,
1159            Self::Term { .. } => &TERM_CATEGORIES,
1160            Self::Text { .. } => &TEXT_CATEGORIES,
1161            Self::TGroup { .. } => &T_GROUP_CATEGORIES,
1162            Self::THead { .. } => &T_HEAD_CATEGORIES,
1163            Self::TRow { .. } => &T_ROW_CATEGORIES,
1164            Self::Title { .. } => &TITLE_CATEGORIES,
1165            Self::TitleReference { .. } => &TITLE_REF_CATEGORIES,
1166            Self::Topic { .. } => &TOPIC_CATEGORIES,
1167            Self::Transition {} => &TRANSITION_CATEGORIES,
1168            Self::UnknownDirective { .. } => &UNKNOWN_DIRECTIVE_CATEGORIES,
1169            Self::Version { .. } => &VERSION_CATEGORIES,
1170            Self::WhiteSpace { .. } => &WHITESPACE_CATEGORIES,
1171
1172            // ============================
1173            //  Sphinx specific directives
1174            // ============================
1175            Self::SphinxOnly { body_indent, .. } => &SPHINX_ONLY_CATEGORIES,
1176            Self::SphinxCodeBlock { .. } => &SPHINX_CODE_BLOCK_CATEGORIES,
1177
1178            // ========================
1179            //  A+ specific directives
1180            // ========================
1181            Self::AplusPOI { .. } => &APLUS_POI_CATEGORIES,
1182            Self::AplusColBreak => &APLUS_COL_BREAK_CATEGORIES,
1183            Self::AplusQuestionnaire { .. } => &APLUS_QUESTIONNAIRE_CATEGORIES,
1184            Self::AplusPickOne { .. } => &APLUS_PICK_ONE_CATEGORIES,
1185            Self::AplusPickAny { .. } => &APLUS_PICK_ANY_CATEGORIES,
1186            Self::AplusFreeText { .. } => &APLUS_FREETEXT_CATEGORIES,
1187            Self::AplusPickChoices { body_indent, .. } => &APLUS_PICK_CHOICES_CATEGORIES,
1188            Self::AplusPickChoice { .. } => &APLUS_PICK_CHOICE_CATEGORIES,
1189            Self::AplusQuestionnaireHints { .. } => &APLUS_QUESTIONNAIRE_HINTS_CATEGORIES,
1190            Self::AplusQuestionnaireHint { .. } => &APLUS_QUESTIONNAIRE_HINT_CATEGORIES,
1191            Self::AplusSubmit { .. } => &APLUS_SUBMIT_CATEGORIES,
1192            Self::AplusActiveElementInput { .. } => &APLUS_ACTIVE_ELEMENT_INPUT_CATEGORIES,
1193            Self::AplusActiveElementOutput { .. } => &APLUS_ACTIVE_ELEMENT_OUTPUT_CATEGORIES,
1194        };
1195
1196        categories.iter()
1197    }
1198}
1199
1200impl std::fmt::Display for TreeNodeType {
1201    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1202        let node_type_str: &str = match self {
1203            Self::Abbreviation { .. } => "abbreviation",
1204            Self::AbsoluteURI { .. } => "absolute URI",
1205            Self::Acronym { .. } => "acronym",
1206            Self::Address => "address",
1207            Self::Admonition { .. } => "admonition",
1208            Self::Attribution { .. } => "attribution",
1209            Self::Author { .. } => "author",
1210            Self::Authors { .. } => "authors",
1211            Self::AutomaticSectionNumbering { .. } => {
1212                todo!("auto section numbering is not really a node?")
1213            }
1214            Self::BlockQuote { .. } => "block quote",
1215            Self::BulletList { .. } => "bullet list",
1216            Self::BulletListItem { .. } => "bullet list item",
1217            Self::Caption { .. } => "caption",
1218            Self::Citation { .. } => "citation",
1219            Self::CitationReference { .. } => "citation reference",
1220            Self::Class { .. } => "class",
1221            Self::Classifier { .. } => "classifier",
1222            Self::Code { .. } => "colspec",
1223            Self::ColSpec { .. } => "colspec",
1224            Self::Comment { .. } => "comment",
1225            Self::CompoundParagraph { .. } => "compound paragraph",
1226            Self::Contact { .. } => "contact",
1227            Self::Container { .. } => "container",
1228            Self::Copyright { .. } => "copyright",
1229            Self::CSVTable { .. } => "csv table",
1230            Self::Date => "date",
1231            Self::Decoration => "decoration",
1232            Self::Definition => "definition",
1233            Self::DefinitionList { .. } => "definition list",
1234            Self::DefinitionListItem { .. } => "definition list item",
1235            Self::Description => "description",
1236            Self::DocInfo => "docinfo",
1237            Self::DoctestBlock { .. } => "doc test block",
1238            Self::Document { .. } => "document",
1239            Self::Emphasis { .. } => "emphasis",
1240            Self::EmptyLine => "emptyline",
1241            Self::Entry { .. } => "entry",
1242            Self::EnumeratedList { .. } => "enumerated list",
1243            Self::EnumeratedListItem { .. } => "enumerated list item",
1244            Self::ExternalHyperlinkTarget { .. } => "external hyperlink target",
1245            Self::Field => "field",
1246            Self::FieldBody { .. } => "field body",
1247            Self::FieldList { .. } => "field list",
1248            Self::FieldListItem { .. } => "field list item",
1249            Self::Figure { .. } => "figure",
1250            Self::Footer { .. } => "footer",
1251            Self::Footnote { .. } => "footnote",
1252            Self::FootnoteReference { .. } => "footnote reference",
1253            Self::Header { .. } => "header",
1254            Self::Generated => "generated",
1255            Self::Image { .. } => "image",
1256            Self::Include { .. } => "include",
1257            Self::IndirectHyperlinkTarget { .. } => "hyperlink target",
1258            Self::Inline { .. } => "inline",
1259            Self::InlineTarget { .. } => "inline target",
1260            Self::InterpretedText { .. } => "interpreted text",
1261            Self::Label { .. } => "label",
1262            Self::Legend { .. } => "legend",
1263            Self::Line { .. } => "line",
1264            Self::LineBlock { .. } => "line block",
1265            Self::ListTable { .. } => "list table",
1266            Self::Literal { .. } => "literal",
1267            Self::LiteralBlock { .. } => "literal block",
1268            Self::Math { .. } => "math",
1269            Self::MathBlock { .. } => "math block",
1270            Self::OptionList { .. } => "option list",
1271            Self::OptionListItem { .. } => "option list item",
1272            Self::OptionString { .. } => "option string",
1273            Self::Organization { .. } => "organization",
1274            Self::Paragraph { .. } => "paragraph",
1275            Self::ParsedLiteralBlock { .. } => "parsed literal block",
1276            Self::Pending { .. } => "pending",
1277            Self::Problematic { .. } => "problematic",
1278            Self::Raw { .. } => "raw",
1279            Self::Reference { .. } => "reference",
1280            Self::Revision { .. } => "revision",
1281            Self::Row { .. } => "row",
1282            Self::Rubric { .. } => "rubric",
1283            Self::Section { .. } => "section",
1284            Self::Sidebar { .. } => "sidebar",
1285            Self::Status { .. } => "status",
1286            Self::StrongEmphasis { .. } => "strong emphasis",
1287            Self::Subscript { .. } => "subscript",
1288            Self::SubstitutionDefinition { .. } => "substitution definition",
1289            Self::SubstitutionReference { .. } => "substitution reference",
1290            Self::Subtitle { .. } => "subtitle",
1291            Self::Superscript { .. } => "superscript",
1292            Self::SystemMessage { .. } => "system message",
1293            Self::Table { .. } => "table",
1294            Self::Target { .. } => "target",
1295            Self::TBody { .. } => "table body",
1296            Self::Term { .. } => "term",
1297            Self::Text { .. } => "text",
1298            Self::TGroup { .. } => "table group",
1299            Self::THead { .. } => "table head",
1300            Self::TRow { .. } => "table row",
1301            Self::Title { .. } => "title",
1302            Self::TitleReference { .. } => "title reference",
1303            Self::Topic { .. } => "topic",
1304            Self::Transition {} => "transition",
1305            Self::UnknownDirective { .. } => "unknown directive",
1306            Self::Version { .. } => "version",
1307            Self::WhiteSpace { .. } => "whitespace",
1308
1309            // ============================
1310            //  Sphinx specific directives
1311            // ============================
1312            Self::SphinxOnly { body_indent, .. } => "sphinx only",
1313            Self::SphinxCodeBlock { .. } => "sphinx code block",
1314
1315            // ========================
1316            //  A+ specific directives
1317            // ========================
1318            Self::AplusPOI { .. } => "aplus point of interest",
1319            Self::AplusColBreak => "aplus column break",
1320            Self::AplusQuestionnaire { .. } => "aplus questionnaire",
1321            Self::AplusPickOne { .. } => "aplus pick one",
1322            Self::AplusPickAny { .. } => "aplus pick any",
1323            Self::AplusFreeText { .. } => "aplus freetext",
1324            Self::AplusPickChoices { body_indent, .. } => "aplus pick choices",
1325            Self::AplusPickChoice { .. } => "aplus pick choice",
1326            Self::AplusQuestionnaireHints { .. } => "aplus questionnaire hints",
1327            Self::AplusQuestionnaireHint { .. } => "aplus questionnaire hint",
1328            Self::AplusSubmit { .. } => "aplus submit",
1329            Self::AplusActiveElementInput { .. } => "aplus active element input",
1330            Self::AplusActiveElementOutput { .. } => "aplus active element output",
1331        };
1332        write!(f, "\"{}\"", node_type_str)
1333    }
1334}