1use duck_diagnostic::Span;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub enum Node {
6 Document(Document),
7 Frontmatter(Frontmatter),
8 Import(Import),
9 Export(Export),
10 Heading(Heading),
11 Paragraph(Paragraph),
12 Text(Text),
13 Bold(Inline),
14 Italic(Inline),
15 Strikethrough(Inline),
16 InlineCode(InlineCode),
17 CodeBlock(CodeBlock),
18 Link(Link),
19 Image(Image),
20 HorizontalRule(HorizontalRule),
21 Blockquote(Blockquote),
22 List(List),
23 ListItem(ListItem),
24 TaskListItem(TaskListItem),
25 Table(Table),
26 TableRow(TableRow),
27 TableCell(TableCell),
28 JsxElement(JsxElement),
29 JsxSelfClosing(JsxSelfClosing),
30 JsxFragment(JsxFragment),
31 JsxExpression(JsxExpression),
32 HardBreak(BreakNode),
33 SoftBreak(BreakNode),
34}
35
36impl Node {
37 pub fn children_of(node: &Node) -> &[Node] {
38 match node {
39 Node::Document(n) => &n.children,
40 Node::Heading(n) => &n.children,
41 Node::Paragraph(n) => &n.children,
42 Node::Bold(n) | Node::Italic(n) | Node::Strikethrough(n) => &n.children,
43 Node::Link(n) => &n.children,
44 Node::Blockquote(n) => &n.children,
45 Node::List(n) => &n.children,
46 Node::ListItem(n) => &n.children,
47 Node::TaskListItem(n) => &n.children,
48 Node::TableCell(n) => &n.children,
49 Node::JsxElement(n) => &n.children,
50 Node::JsxFragment(n) => &n.children,
51 _ => &[],
52 }
53 }
54
55 pub fn children_of_mut(node: &mut Node) -> Option<&mut Vec<Node>> {
56 match node {
57 Node::Document(n) => Some(&mut n.children),
58 Node::Heading(n) => Some(&mut n.children),
59 Node::Paragraph(n) => Some(&mut n.children),
60 Node::Bold(n) | Node::Italic(n) | Node::Strikethrough(n) => Some(&mut n.children),
61 Node::Link(n) => Some(&mut n.children),
62 Node::Blockquote(n) => Some(&mut n.children),
63 Node::List(n) => Some(&mut n.children),
64 Node::ListItem(n) => Some(&mut n.children),
65 Node::TaskListItem(n) => Some(&mut n.children),
66 Node::TableCell(n) => Some(&mut n.children),
67 Node::JsxElement(n) => Some(&mut n.children),
68 Node::JsxFragment(n) => Some(&mut n.children),
69 _ => None,
70 }
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
75pub struct Document {
76 pub children: Vec<Node>,
77 pub span: Span,
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81pub struct Frontmatter {
82 pub raw: String,
83 pub span: Span,
84}
85
86#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
87pub struct Import {
88 pub raw: String,
89 pub span: Span,
90}
91
92#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
93pub struct Export {
94 pub raw: String,
95 pub span: Span,
96}
97
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
99pub struct Heading {
100 pub level: u8,
101 pub children: Vec<Node>,
102 pub span: Span,
103}
104
105impl Heading {
106 pub fn slug(&self) -> String {
109 slug::slugify(Self::plain_text(&self.children))
110 }
111
112 fn plain_text(nodes: &[Node]) -> String {
115 let mut s = String::new();
116 for n in nodes {
117 match n {
118 Node::Text(t) => s.push_str(&t.value),
119 Node::Bold(i) | Node::Italic(i) | Node::Strikethrough(i) => s.push_str(&Self::plain_text(&i.children)),
120 Node::Link(l) => s.push_str(&Self::plain_text(&l.children)),
121 Node::InlineCode(c) => s.push_str(&c.value),
122 _ => {},
123 }
124 }
125 s.trim().to_string()
126 }
127}
128
129#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
130pub struct Paragraph {
131 pub children: Vec<Node>,
132 pub span: Span,
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
136pub struct Text {
137 pub value: String,
138 pub span: Span,
139}
140
141#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
142pub struct Inline {
143 pub children: Vec<Node>,
144 pub span: Span,
145}
146
147#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
148pub struct InlineCode {
149 pub value: String,
150 pub span: Span,
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
154pub struct CodeBlock {
155 pub lang: Option<String>,
156 pub meta: Option<String>,
157 pub value: String,
158 pub span: Span,
159}
160
161#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
162pub struct Link {
163 pub href: String,
164 pub title: Option<String>,
165 pub children: Vec<Node>,
166 pub span: Span,
167}
168
169#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
170pub struct Image {
171 pub src: String,
172 pub alt: String,
173 pub title: Option<String>,
174 pub span: Span,
175}
176
177#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
178pub struct HorizontalRule {
179 pub span: Span,
180}
181
182#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
183pub struct Blockquote {
184 pub children: Vec<Node>,
185 pub span: Span,
186}
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189pub struct List {
190 pub ordered: bool,
191 pub start: Option<u32>,
192 pub children: Vec<Node>,
194 pub span: Span,
195}
196
197#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
198pub struct ListItem {
199 pub children: Vec<Node>,
200 pub span: Span,
201}
202
203#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub struct TaskListItem {
205 pub checked: bool,
206 pub children: Vec<Node>,
207 pub span: Span,
208}
209
210#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
211pub enum TableAlign {
212 None,
213 Left,
214 Right,
215 Center,
216}
217
218#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
219pub struct Table {
220 pub align: Vec<TableAlign>,
221 pub children: Vec<TableRow>,
222 pub span: Span,
223}
224
225#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
226pub struct TableRow {
227 pub cells: Vec<TableCell>,
228 pub span: Span,
229}
230
231#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
232pub struct TableCell {
233 pub children: Vec<Node>,
234 pub span: Span,
235}
236
237#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
238pub struct JsxElement {
239 pub name: String,
240 pub attrs: Vec<crate::ast::JsxAttr>,
241 pub children: Vec<Node>,
242 pub span: Span,
243}
244
245#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
246pub struct JsxSelfClosing {
247 pub name: String,
248 pub attrs: Vec<crate::ast::JsxAttr>,
249 pub span: Span,
250}
251
252#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
253pub struct JsxFragment {
254 pub children: Vec<Node>,
255 pub span: Span,
256}
257
258#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
259pub struct JsxExpression {
260 pub value: String,
261 pub span: Span,
262}
263
264#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
265pub struct BreakNode {
266 pub span: Span,
267}