cmark_writer/ast/node.rs
1//! Node definitions for the CommonMark AST.
2
3use super::custom::CustomNode;
4use super::html::HtmlElement;
5use std::boxed::Box;
6
7/// Main node type, representing an element in a CommonMark document
8#[derive(Debug, Clone, PartialEq)]
9pub enum Node {
10 // Block-level nodes
11 /// Root document node, contains child nodes
12 Document(Vec<Node>),
13
14 /// Heading, contains level (1-6) and inline content
15 Heading {
16 /// Heading level, 1-6
17 level: u8,
18 /// Heading content, containing inline elements
19 content: Vec<Node>,
20 },
21
22 /// Paragraph node, containing inline elements
23 Paragraph(Vec<Node>),
24
25 /// Block quote, containing any block-level elements
26 BlockQuote(Vec<Node>),
27
28 /// Code block, containing optional language identifier and content
29 CodeBlock {
30 /// Optional language identifier
31 language: Option<String>,
32 /// Code content
33 content: String,
34 },
35
36 /// Unordered list, containing list items
37 UnorderedList(Vec<ListItem>),
38
39 /// Ordered list, containing starting number and list items
40 OrderedList {
41 /// List starting number
42 start: u32,
43 /// List items
44 items: Vec<ListItem>,
45 },
46
47 /// Thematic break (horizontal rule)
48 ThematicBreak,
49
50 /// Table
51 Table {
52 /// Header cells
53 headers: Vec<Node>,
54 /// Table rows, each row containing multiple cells
55 rows: Vec<Vec<Node>>,
56 /// Column alignments
57 alignments: Vec<Alignment>,
58 },
59
60 /// HTML block
61 HtmlBlock(String),
62
63 // Inline nodes
64 /// Plain text
65 Text(String),
66
67 /// Emphasis (italic)
68 Emphasis(Vec<Node>),
69
70 /// Strong emphasis (bold)
71 Strong(Vec<Node>),
72
73 /// Strikethrough
74 Strike(Vec<Node>),
75
76 /// Inline code
77 InlineCode(String),
78
79 /// Link
80 Link {
81 /// Link URL
82 url: String,
83 /// Optional link title
84 title: Option<String>,
85 /// Link text
86 content: Vec<Node>,
87 },
88
89 /// Image
90 Image {
91 /// Image URL
92 url: String,
93 /// Optional image title
94 title: Option<String>,
95 /// Alternative text, containing inline elements
96 alt: Vec<Node>,
97 },
98
99 /// Inline element collection, without formatting and line breaks
100 InlineContainer(Vec<Node>),
101
102 /// HTML inline element
103 HtmlElement(HtmlElement),
104
105 /// Soft break (single line break)
106 SoftBreak,
107
108 /// Hard break (two spaces followed by a line break, or backslash followed by a line break)
109 HardBreak,
110
111 /// Custom node that allows users to implement their own writing behavior
112 Custom(Box<dyn CustomNode>),
113}
114
115/// List item type
116#[derive(Debug, Clone, PartialEq)]
117pub enum ListItem {
118 /// Unordered list item
119 Unordered {
120 /// List item content, containing one or more block-level elements
121 content: Vec<Node>,
122 },
123 /// Ordered list item
124 Ordered {
125 /// Optional item number for ordered lists, allowing manual numbering
126 number: Option<u32>,
127 /// List item content, containing one or more block-level elements
128 content: Vec<Node>,
129 },
130}
131
132/// Table column alignment
133#[derive(Debug, Clone, Copy, PartialEq)]
134pub enum Alignment {
135 /// No specific alignment
136 None,
137 /// Left alignment
138 Left,
139 /// Center alignment
140 Center,
141 /// Right alignment
142 Right,
143}
144
145impl Node {
146 /// Check if a node is a block-level node
147 pub fn is_block(&self) -> bool {
148 matches!(
149 self,
150 Node::Document(_)
151 | Node::Heading { .. }
152 | Node::Paragraph(_)
153 | Node::BlockQuote(_)
154 | Node::CodeBlock { .. }
155 | Node::UnorderedList(_)
156 | Node::OrderedList { .. }
157 | Node::ThematicBreak
158 | Node::Table { .. }
159 | Node::HtmlBlock(_)
160 | Node::Custom(_)
161 )
162 }
163
164 /// Check if a node is an inline node
165 pub fn is_inline(&self) -> bool {
166 matches!(
167 self,
168 Node::Text(_)
169 | Node::Emphasis(_)
170 | Node::Strong(_)
171 | Node::Strike(_)
172 | Node::InlineCode(_)
173 | Node::Link { .. }
174 | Node::Image { .. }
175 | Node::InlineContainer(_)
176 | Node::HtmlElement(_)
177 | Node::SoftBreak
178 | Node::HardBreak
179 | Node::Custom(_)
180 )
181 }
182}