Skip to main content

socketry_markdown/
mdast.rs

1// Released under the MIT License.
2// Copyright, 2022, by Bernhard Berger.
3// Copyright, 2022-2025, by Titus Wormer.
4// Copyright, 2023, by Kyle McCarthy.
5// Copyright, 2023, by Mia.
6// Copyright, 2023, by Rafael Bachmann.
7// Copyright, 2024, by Harsha Teja Kanna.
8// Copyright, 2026, by Samuel Williams.
9
10//! markdown syntax tree: [mdast][].
11//!
12//! [mdast]: https://github.com/syntax-tree/mdast
13use crate::unist::Position;
14use alloc::{
15    fmt,
16    string::{String, ToString},
17    vec::Vec,
18};
19
20mod headings;
21pub use headings::{HeadingEntry, HeadingOptions, Headings};
22
23/// MDX: relative byte index into a string, to an absolute byte index into the
24/// whole document.
25pub type Stop = (usize, usize);
26
27/// Explicitness of a reference.
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
29#[cfg_attr(
30    feature = "serde",
31    derive(serde::Serialize, serde::Deserialize),
32    serde(rename_all = "lowercase")
33)]
34pub enum ReferenceKind {
35    /// The reference is implicit, its identifier inferred from its content.
36    Shortcut,
37    /// The reference is explicit, its identifier inferred from its content.
38    Collapsed,
39    /// The reference is explicit, its identifier explicitly set.
40    Full,
41}
42
43/// GFM: alignment of phrasing content.
44///
45/// Used to align the contents of table cells within a table.
46#[derive(Clone, Copy, Debug, Eq, PartialEq)]
47pub enum AlignKind {
48    /// Left alignment.
49    ///
50    /// See the `left` value of the `text-align` CSS property.
51    ///
52    /// ```markdown
53    ///   | | aaa |
54    /// > | | :-- |
55    ///       ^^^
56    /// ```
57    Left,
58    /// Right alignment.
59    ///
60    /// See the `right` value of the `text-align` CSS property.
61    ///
62    /// ```markdown
63    ///   | | aaa |
64    /// > | | --: |
65    ///       ^^^
66    /// ```
67    Right,
68    /// Center alignment.
69    ///
70    /// See the `center` value of the `text-align` CSS property.
71    ///
72    /// ```markdown
73    ///   | | aaa |
74    /// > | | :-: |
75    ///       ^^^
76    /// ```
77    Center,
78    /// No alignment.
79    ///
80    /// Phrasing content is aligned as defined by the host environment.
81    ///
82    /// ```markdown
83    ///   | | aaa |
84    /// > | | --- |
85    ///       ^^^
86    /// ```
87    None,
88}
89
90/// Implement serde according to <https://github.com/syntax-tree/mdast#aligntype>
91#[cfg(feature = "serde")]
92impl serde::ser::Serialize for AlignKind {
93    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94    where
95        S: serde::ser::Serializer,
96    {
97        match self {
98            AlignKind::Left => serializer.serialize_unit_variant("AlignKind", 0, "left"),
99            AlignKind::Right => serializer.serialize_unit_variant("AlignKind", 1, "right"),
100            AlignKind::Center => serializer.serialize_unit_variant("AlignKind", 2, "center"),
101            AlignKind::None => serializer.serialize_none(),
102        }
103    }
104}
105
106#[cfg(feature = "serde")]
107struct AlignKindVisitor;
108
109#[cfg(feature = "serde")]
110impl serde::de::Visitor<'_> for AlignKindVisitor {
111    type Value = AlignKind;
112
113    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114        formatter.write_str("'left', 'right', 'center' or null")
115    }
116
117    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
118    where
119        E: serde::de::Error,
120    {
121        match v {
122            "left" => Ok(AlignKind::Left),
123            "right" => Ok(AlignKind::Right),
124            "center" => Ok(AlignKind::Center),
125            &_ => Err(serde::de::Error::invalid_type(
126                serde::de::Unexpected::Str(v),
127                &self,
128            )),
129        }
130    }
131
132    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
133    where
134        E: serde::de::Error,
135    {
136        match v {
137            b"left" => Ok(AlignKind::Left),
138            b"right" => Ok(AlignKind::Right),
139            b"center" => Ok(AlignKind::Center),
140            &_ => Err(serde::de::Error::invalid_type(
141                serde::de::Unexpected::Bytes(v),
142                &self,
143            )),
144        }
145    }
146
147    fn visit_none<E>(self) -> Result<Self::Value, E>
148    where
149        E: serde::de::Error,
150    {
151        Ok(AlignKind::None)
152    }
153
154    fn visit_unit<E>(self) -> Result<Self::Value, E>
155    where
156        E: serde::de::Error,
157    {
158        Ok(AlignKind::None)
159    }
160}
161
162#[cfg(feature = "serde")]
163impl<'de> serde::de::Deserialize<'de> for AlignKind {
164    fn deserialize<D>(deserializer: D) -> Result<AlignKind, D::Error>
165    where
166        D: serde::de::Deserializer<'de>,
167    {
168        deserializer.deserialize_any(AlignKindVisitor)
169    }
170}
171
172/// Nodes.
173#[derive(Clone, Eq, PartialEq)]
174#[cfg_attr(
175    feature = "serde",
176    derive(serde::Serialize, serde::Deserialize),
177    serde(tag = "type", rename_all = "camelCase")
178)]
179pub enum Node {
180    // Document:
181    /// Root.
182    Root(Root),
183
184    // Container:
185    /// A transparent fragment containing a sequence of nodes.
186    ///
187    /// Fragments are useful for holding children extracted from another node.
188    Fragment(Fragment),
189    /// Block quote.
190    Blockquote(Blockquote),
191    /// Footnote definition.
192    FootnoteDefinition(FootnoteDefinition),
193    /// MDX: JSX element (container).
194    MdxJsxFlowElement(MdxJsxFlowElement),
195    /// List.
196    List(List),
197
198    // Frontmatter:
199    /// MDX.js ESM.
200    MdxjsEsm(MdxjsEsm),
201    /// Toml.
202    Toml(Toml),
203    /// Yaml.
204    Yaml(Yaml),
205
206    // Phrasing:
207    /// Break.
208    Break(Break),
209    /// Code (phrasing).
210    InlineCode(InlineCode),
211    /// Math (phrasing).
212    InlineMath(InlineMath),
213    /// Delete.
214    Delete(Delete),
215    /// Emphasis.
216    Emphasis(Emphasis),
217    // MDX: expression (text).
218    MdxTextExpression(MdxTextExpression),
219    /// Footnote reference.
220    FootnoteReference(FootnoteReference),
221    /// Html (phrasing).
222    Html(Html),
223    /// Image.
224    Image(Image),
225    /// Image reference.
226    ImageReference(ImageReference),
227    // MDX: JSX element (text).
228    MdxJsxTextElement(MdxJsxTextElement),
229    /// Link.
230    Link(Link),
231    /// Link reference.
232    LinkReference(LinkReference),
233    /// Strong
234    Strong(Strong),
235    /// Text.
236    Text(Text),
237
238    // Flow:
239    /// Code (flow).
240    Code(Code),
241    /// Math (flow).
242    Math(Math),
243    // MDX: expression (flow).
244    MdxFlowExpression(MdxFlowExpression),
245    /// Heading.
246    Heading(Heading),
247    /// Html (flow).
248    // Html(Html),
249    /// Table.
250    Table(Table),
251    /// Thematic break.
252    ThematicBreak(ThematicBreak),
253
254    // Table content.
255    /// Table row.
256    TableRow(TableRow),
257
258    // Row content.
259    /// Table cell.
260    TableCell(TableCell),
261
262    // List content.
263    /// List item.
264    ListItem(ListItem),
265
266    // Content.
267    /// Definition.
268    Definition(Definition),
269    /// Paragraph.
270    Paragraph(Paragraph),
271}
272
273impl fmt::Debug for Node {
274    // Debug the wrapped struct.
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        match self {
277            Node::Root(x) => x.fmt(f),
278            Node::Fragment(x) => x.fmt(f),
279            Node::Blockquote(x) => x.fmt(f),
280            Node::FootnoteDefinition(x) => x.fmt(f),
281            Node::MdxJsxFlowElement(x) => x.fmt(f),
282            Node::List(x) => x.fmt(f),
283            Node::MdxjsEsm(x) => x.fmt(f),
284            Node::Toml(x) => x.fmt(f),
285            Node::Yaml(x) => x.fmt(f),
286            Node::Break(x) => x.fmt(f),
287            Node::InlineCode(x) => x.fmt(f),
288            Node::InlineMath(x) => x.fmt(f),
289            Node::Delete(x) => x.fmt(f),
290            Node::Emphasis(x) => x.fmt(f),
291            Node::MdxTextExpression(x) => x.fmt(f),
292            Node::FootnoteReference(x) => x.fmt(f),
293            Node::Html(x) => x.fmt(f),
294            Node::Image(x) => x.fmt(f),
295            Node::ImageReference(x) => x.fmt(f),
296            Node::MdxJsxTextElement(x) => x.fmt(f),
297            Node::Link(x) => x.fmt(f),
298            Node::LinkReference(x) => x.fmt(f),
299            Node::Strong(x) => x.fmt(f),
300            Node::Text(x) => x.fmt(f),
301            Node::Code(x) => x.fmt(f),
302            Node::Math(x) => x.fmt(f),
303            Node::MdxFlowExpression(x) => x.fmt(f),
304            Node::Heading(x) => x.fmt(f),
305            Node::Table(x) => x.fmt(f),
306            Node::ThematicBreak(x) => x.fmt(f),
307            Node::TableRow(x) => x.fmt(f),
308            Node::TableCell(x) => x.fmt(f),
309            Node::ListItem(x) => x.fmt(f),
310            Node::Definition(x) => x.fmt(f),
311            Node::Paragraph(x) => x.fmt(f),
312        }
313    }
314}
315
316fn children_to_string(children: &[Node]) -> String {
317    children.iter().map(ToString::to_string).collect()
318}
319
320// To do: clippy may be right but that’s a breaking change.
321#[allow(clippy::to_string_trait_impl)]
322impl ToString for Node {
323    fn to_string(&self) -> String {
324        match self {
325            // Parents.
326            Node::Root(x) => children_to_string(&x.children),
327            Node::Fragment(x) => children_to_string(&x.children),
328            Node::Blockquote(x) => children_to_string(&x.children),
329            Node::FootnoteDefinition(x) => children_to_string(&x.children),
330            Node::MdxJsxFlowElement(x) => children_to_string(&x.children),
331            Node::List(x) => children_to_string(&x.children),
332            Node::Delete(x) => children_to_string(&x.children),
333            Node::Emphasis(x) => children_to_string(&x.children),
334            Node::MdxJsxTextElement(x) => children_to_string(&x.children),
335            Node::Link(x) => children_to_string(&x.children),
336            Node::LinkReference(x) => children_to_string(&x.children),
337            Node::Strong(x) => children_to_string(&x.children),
338            Node::Heading(x) => children_to_string(&x.children),
339            Node::Table(x) => children_to_string(&x.children),
340            Node::TableRow(x) => children_to_string(&x.children),
341            Node::TableCell(x) => children_to_string(&x.children),
342            Node::ListItem(x) => children_to_string(&x.children),
343            Node::Paragraph(x) => children_to_string(&x.children),
344
345            // Literals.
346            Node::MdxjsEsm(x) => x.value.clone(),
347            Node::Toml(x) => x.value.clone(),
348            Node::Yaml(x) => x.value.clone(),
349            Node::InlineCode(x) => x.value.clone(),
350            Node::InlineMath(x) => x.value.clone(),
351            Node::MdxTextExpression(x) => x.value.clone(),
352            Node::Html(x) => x.value.clone(),
353            Node::Text(x) => x.value.clone(),
354            Node::Code(x) => x.value.clone(),
355            Node::Math(x) => x.value.clone(),
356            Node::MdxFlowExpression(x) => x.value.clone(),
357
358            // Voids.
359            Node::Break(_)
360            | Node::FootnoteReference(_)
361            | Node::Image(_)
362            | Node::ImageReference(_)
363            | Node::ThematicBreak(_)
364            | Node::Definition(_) => String::new(),
365        }
366    }
367}
368
369impl Node {
370    #[must_use]
371    pub fn children(&self) -> Option<&Vec<Node>> {
372        match self {
373            // Parent.
374            Node::Root(x) => Some(&x.children),
375            Node::Fragment(x) => Some(&x.children),
376            Node::Paragraph(x) => Some(&x.children),
377            Node::Heading(x) => Some(&x.children),
378            Node::Blockquote(x) => Some(&x.children),
379            Node::List(x) => Some(&x.children),
380            Node::ListItem(x) => Some(&x.children),
381            Node::Emphasis(x) => Some(&x.children),
382            Node::Strong(x) => Some(&x.children),
383            Node::Link(x) => Some(&x.children),
384            Node::LinkReference(x) => Some(&x.children),
385            Node::FootnoteDefinition(x) => Some(&x.children),
386            Node::Table(x) => Some(&x.children),
387            Node::TableRow(x) => Some(&x.children),
388            Node::TableCell(x) => Some(&x.children),
389            Node::Delete(x) => Some(&x.children),
390            Node::MdxJsxFlowElement(x) => Some(&x.children),
391            Node::MdxJsxTextElement(x) => Some(&x.children),
392            // Non-parent.
393            _ => None,
394        }
395    }
396
397    pub fn children_mut(&mut self) -> Option<&mut Vec<Node>> {
398        match self {
399            // Parent.
400            Node::Root(x) => Some(&mut x.children),
401            Node::Fragment(x) => Some(&mut x.children),
402            Node::Paragraph(x) => Some(&mut x.children),
403            Node::Heading(x) => Some(&mut x.children),
404            Node::Blockquote(x) => Some(&mut x.children),
405            Node::List(x) => Some(&mut x.children),
406            Node::ListItem(x) => Some(&mut x.children),
407            Node::Emphasis(x) => Some(&mut x.children),
408            Node::Strong(x) => Some(&mut x.children),
409            Node::Link(x) => Some(&mut x.children),
410            Node::LinkReference(x) => Some(&mut x.children),
411            Node::FootnoteDefinition(x) => Some(&mut x.children),
412            Node::Table(x) => Some(&mut x.children),
413            Node::TableRow(x) => Some(&mut x.children),
414            Node::TableCell(x) => Some(&mut x.children),
415            Node::Delete(x) => Some(&mut x.children),
416            Node::MdxJsxFlowElement(x) => Some(&mut x.children),
417            Node::MdxJsxTextElement(x) => Some(&mut x.children),
418            // Non-parent.
419            _ => None,
420        }
421    }
422
423    #[must_use]
424    pub fn position(&self) -> Option<&Position> {
425        match self {
426            Node::Root(x) => x.position.as_ref(),
427            Node::Fragment(_) => None,
428            Node::Blockquote(x) => x.position.as_ref(),
429            Node::FootnoteDefinition(x) => x.position.as_ref(),
430            Node::MdxJsxFlowElement(x) => x.position.as_ref(),
431            Node::List(x) => x.position.as_ref(),
432            Node::MdxjsEsm(x) => x.position.as_ref(),
433            Node::Toml(x) => x.position.as_ref(),
434            Node::Yaml(x) => x.position.as_ref(),
435            Node::Break(x) => x.position.as_ref(),
436            Node::InlineCode(x) => x.position.as_ref(),
437            Node::InlineMath(x) => x.position.as_ref(),
438            Node::Delete(x) => x.position.as_ref(),
439            Node::Emphasis(x) => x.position.as_ref(),
440            Node::MdxTextExpression(x) => x.position.as_ref(),
441            Node::FootnoteReference(x) => x.position.as_ref(),
442            Node::Html(x) => x.position.as_ref(),
443            Node::Image(x) => x.position.as_ref(),
444            Node::ImageReference(x) => x.position.as_ref(),
445            Node::MdxJsxTextElement(x) => x.position.as_ref(),
446            Node::Link(x) => x.position.as_ref(),
447            Node::LinkReference(x) => x.position.as_ref(),
448            Node::Strong(x) => x.position.as_ref(),
449            Node::Text(x) => x.position.as_ref(),
450            Node::Code(x) => x.position.as_ref(),
451            Node::Math(x) => x.position.as_ref(),
452            Node::MdxFlowExpression(x) => x.position.as_ref(),
453            Node::Heading(x) => x.position.as_ref(),
454            Node::Table(x) => x.position.as_ref(),
455            Node::ThematicBreak(x) => x.position.as_ref(),
456            Node::TableRow(x) => x.position.as_ref(),
457            Node::TableCell(x) => x.position.as_ref(),
458            Node::ListItem(x) => x.position.as_ref(),
459            Node::Definition(x) => x.position.as_ref(),
460            Node::Paragraph(x) => x.position.as_ref(),
461        }
462    }
463
464    pub fn position_mut(&mut self) -> Option<&mut Position> {
465        match self {
466            Node::Root(x) => x.position.as_mut(),
467            Node::Fragment(_) => None,
468            Node::Blockquote(x) => x.position.as_mut(),
469            Node::FootnoteDefinition(x) => x.position.as_mut(),
470            Node::MdxJsxFlowElement(x) => x.position.as_mut(),
471            Node::List(x) => x.position.as_mut(),
472            Node::MdxjsEsm(x) => x.position.as_mut(),
473            Node::Toml(x) => x.position.as_mut(),
474            Node::Yaml(x) => x.position.as_mut(),
475            Node::Break(x) => x.position.as_mut(),
476            Node::InlineCode(x) => x.position.as_mut(),
477            Node::InlineMath(x) => x.position.as_mut(),
478            Node::Delete(x) => x.position.as_mut(),
479            Node::Emphasis(x) => x.position.as_mut(),
480            Node::MdxTextExpression(x) => x.position.as_mut(),
481            Node::FootnoteReference(x) => x.position.as_mut(),
482            Node::Html(x) => x.position.as_mut(),
483            Node::Image(x) => x.position.as_mut(),
484            Node::ImageReference(x) => x.position.as_mut(),
485            Node::MdxJsxTextElement(x) => x.position.as_mut(),
486            Node::Link(x) => x.position.as_mut(),
487            Node::LinkReference(x) => x.position.as_mut(),
488            Node::Strong(x) => x.position.as_mut(),
489            Node::Text(x) => x.position.as_mut(),
490            Node::Code(x) => x.position.as_mut(),
491            Node::Math(x) => x.position.as_mut(),
492            Node::MdxFlowExpression(x) => x.position.as_mut(),
493            Node::Heading(x) => x.position.as_mut(),
494            Node::Table(x) => x.position.as_mut(),
495            Node::ThematicBreak(x) => x.position.as_mut(),
496            Node::TableRow(x) => x.position.as_mut(),
497            Node::TableCell(x) => x.position.as_mut(),
498            Node::ListItem(x) => x.position.as_mut(),
499            Node::Definition(x) => x.position.as_mut(),
500            Node::Paragraph(x) => x.position.as_mut(),
501        }
502    }
503
504    pub fn position_set(&mut self, position: Option<Position>) {
505        match self {
506            Node::Root(x) => x.position = position,
507            Node::Fragment(_) => (),
508            Node::Blockquote(x) => x.position = position,
509            Node::FootnoteDefinition(x) => x.position = position,
510            Node::MdxJsxFlowElement(x) => x.position = position,
511            Node::List(x) => x.position = position,
512            Node::MdxjsEsm(x) => x.position = position,
513            Node::Toml(x) => x.position = position,
514            Node::Yaml(x) => x.position = position,
515            Node::Break(x) => x.position = position,
516            Node::InlineCode(x) => x.position = position,
517            Node::InlineMath(x) => x.position = position,
518            Node::Delete(x) => x.position = position,
519            Node::Emphasis(x) => x.position = position,
520            Node::MdxTextExpression(x) => x.position = position,
521            Node::FootnoteReference(x) => x.position = position,
522            Node::Html(x) => x.position = position,
523            Node::Image(x) => x.position = position,
524            Node::ImageReference(x) => x.position = position,
525            Node::MdxJsxTextElement(x) => x.position = position,
526            Node::Link(x) => x.position = position,
527            Node::LinkReference(x) => x.position = position,
528            Node::Strong(x) => x.position = position,
529            Node::Text(x) => x.position = position,
530            Node::Code(x) => x.position = position,
531            Node::Math(x) => x.position = position,
532            Node::MdxFlowExpression(x) => x.position = position,
533            Node::Heading(x) => x.position = position,
534            Node::Table(x) => x.position = position,
535            Node::ThematicBreak(x) => x.position = position,
536            Node::TableRow(x) => x.position = position,
537            Node::TableCell(x) => x.position = position,
538            Node::ListItem(x) => x.position = position,
539            Node::Definition(x) => x.position = position,
540            Node::Paragraph(x) => x.position = position,
541        }
542    }
543
544    /// Visit this node and its descendants in depth-first, pre-order.
545    pub fn walk<'a>(&'a self, mut visitor: impl FnMut(&'a Node)) {
546        fn visit<'a>(node: &'a Node, visitor: &mut impl FnMut(&'a Node)) {
547            visitor(node);
548            if let Some(children) = node.children() {
549                for child in children {
550                    visit(child, visitor);
551                }
552            }
553        }
554
555        visit(self, &mut visitor);
556    }
557
558    /// Mutably visit this node and its descendants in depth-first, pre-order.
559    pub fn walk_mut(&mut self, mut visitor: impl FnMut(&mut Node)) {
560        fn visit(node: &mut Node, visitor: &mut impl FnMut(&mut Node)) {
561            visitor(node);
562            if let Some(children) = node.children_mut() {
563                for child in children {
564                    visit(child, visitor);
565                }
566            }
567        }
568
569        visit(self, &mut visitor);
570    }
571
572    /// Return the concatenated text represented by this node.
573    ///
574    /// Image nodes contribute their alt text and hard breaks contribute a
575    /// newline. Structural nodes concatenate the text of their children.
576    #[must_use]
577    pub fn text_content(&self) -> String {
578        match self {
579            Node::Image(node) => node.alt.clone(),
580            Node::ImageReference(node) => node.alt.clone(),
581            Node::Break(_) => "\n".into(),
582            Node::Definition(_) | Node::FootnoteReference(_) | Node::ThematicBreak(_) => {
583                String::new()
584            }
585            _ => {
586                if let Some(children) = self.children() {
587                    children.iter().map(Node::text_content).collect()
588                } else {
589                    self.to_string()
590                }
591            }
592        }
593    }
594
595    /// Find a direct child heading with the requested text.
596    #[must_use]
597    pub fn find_heading(&self, title: &str) -> Option<&Node> {
598        self.children()?
599            .iter()
600            .find(|child| matches!(child, Node::Heading(_)) && child.text_content() == title)
601    }
602
603    /// Return the language identifier of inline or fenced code.
604    #[must_use]
605    pub fn code_language(&self) -> Option<&str> {
606        match self {
607            Node::InlineCode(node) => node.lang.as_deref(),
608            Node::Code(node) => node.lang.as_deref(),
609            _ => None,
610        }
611    }
612
613    /// Return code metadata for inline or fenced code.
614    ///
615    /// Inline code metadata is its language token. Fenced code metadata is
616    /// reconstructed from `lang` and `meta` when either is present.
617    #[must_use]
618    pub fn code_info(&self) -> Option<String> {
619        match self {
620            Node::InlineCode(node) => node.lang.clone(),
621            Node::Code(node) => match (&node.lang, &node.meta) {
622                (Some(lang), Some(meta)) => Some(alloc::format!("{lang} {meta}")),
623                (Some(lang), None) => Some(lang.clone()),
624                (None, Some(meta)) => Some(meta.clone()),
625                (None, None) => None,
626            },
627            _ => None,
628        }
629    }
630
631    /// Take all direct children from this node and return them in a fragment.
632    ///
633    /// Returns `None` for nodes that cannot contain children. The extracted
634    /// child nodes retain their own positions; the new fragment has no source
635    /// position of its own.
636    pub fn extract_children(&mut self) -> Option<Node> {
637        self.children_mut().map(|children| {
638            Node::Fragment(Fragment {
639                children: core::mem::take(children),
640            })
641        })
642    }
643
644    /// Render this node with a user-provided renderer.
645    pub fn render_with<R: crate::renderer::Renderer>(&self, renderer: &mut R) -> String {
646        renderer.render(self)
647    }
648
649    /// Serialize this AST node or fragment as Markdown.
650    ///
651    /// Markdown output ends with a newline. For custom formatting, use
652    /// [`to_markdown_with_options`][crate::markdown::to_markdown_with_options].
653    ///
654    /// # Example
655    ///
656    /// ```ignore
657    /// let markdown = node.to_markdown();
658    /// ```
659    #[must_use]
660    pub fn to_markdown(&self) -> String {
661        crate::markdown::to_markdown(self).expect("Markdown serialization failed for this AST node")
662    }
663
664    /// Serialize this AST node or fragment as Markdown with custom options.
665    ///
666    /// # Errors
667    ///
668    /// Returns an error if an option contains an invalid marker or the AST
669    /// contains a node that cannot be serialized.
670    pub fn to_markdown_with_options(
671        &self,
672        options: &crate::markdown::Options,
673    ) -> Result<String, crate::message::Message> {
674        crate::markdown::to_markdown_with_options(self, options)
675    }
676
677    /// Replace a heading and the section below it in this node's children.
678    ///
679    /// `heading_index` is the direct-child index of the heading. When
680    /// `replace_heading` is false, the heading stays and only its section
681    /// content is replaced. When `remove_subsections` is true, nested heading
682    /// sections are included through the next heading of the same or higher
683    /// level. Returns `false` if the index is not a heading.
684    pub fn replace_heading_section(
685        &mut self,
686        heading_index: usize,
687        replacement: Vec<Node>,
688        replace_heading: bool,
689        remove_subsections: bool,
690    ) -> bool {
691        let Some(children) = self.children_mut() else {
692            return false;
693        };
694        let depth = match children.get(heading_index) {
695            Some(Node::Heading(heading)) => heading.depth,
696            _ => return false,
697        };
698        let end = children
699            .iter()
700            .enumerate()
701            .skip(heading_index + 1)
702            .find_map(|(index, node)| {
703                let Node::Heading(next) = node else {
704                    return None;
705                };
706                if !remove_subsections || next.depth <= depth {
707                    Some(index)
708                } else {
709                    None
710                }
711            })
712            .unwrap_or(children.len());
713        let start = if replace_heading {
714            heading_index
715        } else {
716            heading_index + 1
717        };
718
719        children.splice(start..end, replacement);
720        true
721    }
722}
723
724/// MDX: attribute content.
725#[derive(Clone, Debug, Eq, PartialEq)]
726#[cfg_attr(
727    feature = "serde",
728    derive(serde::Serialize, serde::Deserialize),
729    serde(untagged)
730)]
731pub enum AttributeContent {
732    /// JSX expression.
733    ///
734    /// ```markdown
735    /// > | <a {...b} />
736    ///        ^^^^^^
737    /// ```
738    Expression(MdxJsxExpressionAttribute),
739    /// JSX property.
740    ///
741    /// ```markdown
742    /// > | <a b />
743    ///        ^
744    /// ```
745    Property(MdxJsxAttribute),
746}
747//
748#[derive(Clone, Debug, Eq, PartialEq)]
749#[cfg_attr(
750    feature = "serde",
751    derive(serde::Serialize, serde::Deserialize),
752    serde(tag = "type", rename = "mdxJsxAttributeValueExpression")
753)]
754pub struct AttributeValueExpression {
755    pub value: String,
756    #[cfg_attr(feature = "serde", serde(rename = "_markdownRsStops"))]
757    pub stops: Vec<Stop>,
758}
759
760/// MDX: attribute value.
761#[derive(Clone, Debug, Eq, PartialEq)]
762#[cfg_attr(
763    feature = "serde",
764    derive(serde::Serialize, serde::Deserialize),
765    serde(untagged)
766)]
767pub enum AttributeValue {
768    /// Expression value.
769    ///
770    /// ```markdown
771    /// > | <a b={c} />
772    ///          ^^^
773    /// ```
774    Expression(AttributeValueExpression),
775    /// Static value.
776    ///
777    /// ```markdown
778    /// > | <a b="c" />
779    ///          ^^^
780    /// ```
781    Literal(String),
782}
783
784/// A transparent container for a sequence of AST nodes.
785///
786/// Fragments have no source position of their own. They are useful for holding
787/// the children extracted from another node.
788#[derive(Clone, Debug, Eq, PartialEq)]
789#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
790pub struct Fragment {
791    /// Content model.
792    pub children: Vec<Node>,
793}
794
795/// Document.
796///
797/// ```markdown
798/// > | a
799///     ^
800/// ```
801#[derive(Clone, Debug, Eq, PartialEq)]
802#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
803pub struct Root {
804    // Parent.
805    /// Content model.
806    pub children: Vec<Node>,
807    /// Positional info.
808    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
809    pub position: Option<Position>,
810}
811
812/// Paragraph.
813///
814/// ```markdown
815/// > | a
816///     ^
817/// ```
818#[derive(Clone, Debug, Eq, PartialEq)]
819#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
820pub struct Paragraph {
821    // Parent.
822    /// Content model.
823    pub children: Vec<Node>,
824    /// Positional info.
825    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
826    pub position: Option<Position>,
827}
828
829/// Heading.
830///
831/// ```markdown
832/// > | # a
833///     ^^^
834/// ```
835#[derive(Clone, Debug, Eq, PartialEq)]
836#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
837pub struct Heading {
838    // Parent.
839    /// Content model.
840    pub children: Vec<Node>,
841    /// Positional info.
842    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
843    pub position: Option<Position>,
844    // Extra.
845    /// Rank (between `1` and `6`, both including).
846    pub depth: u8,
847}
848
849/// Thematic break.
850///
851/// ```markdown
852/// > | ***
853///     ^^^
854/// ```
855#[derive(Clone, Debug, Eq, PartialEq)]
856#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
857pub struct ThematicBreak {
858    // Void.
859    /// Positional info.
860    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
861    pub position: Option<Position>,
862}
863
864/// Block quote.
865///
866/// ```markdown
867/// > | > a
868///     ^^^
869/// ```
870#[derive(Clone, Debug, Eq, PartialEq)]
871#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
872pub struct Blockquote {
873    // Parent.
874    /// Content model.
875    pub children: Vec<Node>,
876    /// Positional info.
877    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
878    pub position: Option<Position>,
879}
880
881/// List.
882///
883/// ```markdown
884/// > | * a
885///     ^^^
886/// ```
887#[derive(Clone, Debug, Eq, PartialEq)]
888#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
889pub struct List {
890    // Parent.
891    /// Content model.
892    pub children: Vec<Node>,
893    /// Positional info.
894    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
895    pub position: Option<Position>,
896    // Extra.
897    /// Ordered (`true`) or unordered (`false`).
898    pub ordered: bool,
899    /// Starting number of the list.
900    /// `None` when unordered.
901    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
902    pub start: Option<u32>,
903    /// One or more of its children are separated with a blank line from its
904    /// siblings (when `true`), or not (when `false`).
905    pub spread: bool,
906}
907
908/// List item.
909///
910/// ```markdown
911/// > | * a
912///     ^^^
913/// ```
914#[derive(Clone, Debug, Eq, PartialEq)]
915#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
916pub struct ListItem {
917    // Parent.
918    /// Content model.
919    pub children: Vec<Node>,
920    /// Positional info.
921    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
922    pub position: Option<Position>,
923    // Extra.
924    /// The item contains two or more children separated by a blank line
925    /// (when `true`), or not (when `false`).
926    pub spread: bool,
927    /// GFM: whether the item is done (when `true`), not done (when `false`),
928    /// or indeterminate or not applicable (`None`).
929    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
930    pub checked: Option<bool>,
931}
932
933/// Html (flow or phrasing).
934///
935/// ```markdown
936/// > | <a>
937///     ^^^
938/// ```
939#[derive(Clone, Debug, Eq, PartialEq)]
940#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
941pub struct Html {
942    // Text.
943    /// Content model.
944    pub value: String,
945    /// Positional info.
946    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
947    pub position: Option<Position>,
948}
949
950/// Code (flow).
951///
952/// ```markdown
953/// > | ~~~
954///     ^^^
955/// > | a
956///     ^
957/// > | ~~~
958///     ^^^
959/// ```
960#[derive(Clone, Debug, Eq, PartialEq)]
961#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
962pub struct Code {
963    // Text.
964    /// Content model.
965    pub value: String,
966    /// Positional info.
967    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
968    pub position: Option<Position>,
969    // Extra.
970    /// The language of computer code being marked up.
971    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
972    pub lang: Option<String>,
973    /// Custom info relating to the node.
974    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
975    pub meta: Option<String>,
976}
977
978/// Math (flow).
979///
980/// ```markdown
981/// > | $$
982///     ^^
983/// > | a
984///     ^
985/// > | $$
986///     ^^
987/// ```
988#[derive(Clone, Debug, Eq, PartialEq)]
989#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
990pub struct Math {
991    // Text.
992    /// Content model.
993    pub value: String,
994    /// Positional info.
995    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
996    pub position: Option<Position>,
997    // Extra.
998    /// Custom info relating to the node.
999    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1000    pub meta: Option<String>,
1001}
1002
1003/// Definition.
1004///
1005/// ```markdown
1006/// > | [a]: b
1007///     ^^^^^^
1008/// ```
1009#[derive(Clone, Debug, Eq, PartialEq)]
1010#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1011pub struct Definition {
1012    // Void.
1013    /// Positional info.
1014    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1015    pub position: Option<Position>,
1016    // Resource.
1017    /// URL to the referenced resource.
1018    pub url: String,
1019    /// Advisory info for the resource, such as something that would be
1020    /// appropriate for a tooltip.
1021    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1022    pub title: Option<String>,
1023    // Association.
1024    /// Value that can match another node.
1025    /// `identifier` is a source value: character escapes and character references
1026    /// are *not* parsed.
1027    /// Its value must be normalized.
1028    pub identifier: String,
1029    /// `label` is a string value: it works just like `title` on a link or a
1030    /// `lang` on code: character escapes and character references are parsed.
1031    ///
1032    /// To normalize a value, collapse markdown whitespace (`[\t\n\r ]+`) to a
1033    /// space, trim the optional initial and/or final space, and perform
1034    /// case-folding.
1035    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1036    pub label: Option<String>,
1037}
1038
1039/// Text.
1040///
1041/// ```markdown
1042/// > | a
1043///     ^
1044/// ```
1045#[derive(Clone, Debug, Eq, PartialEq)]
1046#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1047pub struct Text {
1048    // Text.
1049    /// Content model.
1050    pub value: String,
1051    /// Positional info.
1052    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1053    pub position: Option<Position>,
1054}
1055
1056/// Emphasis.
1057///
1058/// ```markdown
1059/// > | *a*
1060///     ^^^
1061/// ```
1062#[derive(Clone, Debug, Eq, PartialEq)]
1063#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1064pub struct Emphasis {
1065    // Parent.
1066    /// Content model.
1067    pub children: Vec<Node>,
1068    /// Positional info.
1069    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1070    pub position: Option<Position>,
1071}
1072
1073/// Strong.
1074///
1075/// ```markdown
1076/// > | **a**
1077///     ^^^^^
1078/// ```
1079#[derive(Clone, Debug, Eq, PartialEq)]
1080#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1081pub struct Strong {
1082    // Parent.
1083    /// Content model.
1084    pub children: Vec<Node>,
1085    /// Positional info.
1086    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1087    pub position: Option<Position>,
1088}
1089
1090/// Code (phrasing).
1091///
1092/// ```markdown
1093/// > | `a`
1094///     ^^^
1095/// ```
1096#[derive(Clone, Debug, Eq, PartialEq)]
1097#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1098pub struct InlineCode {
1099    // Text.
1100    /// Content model.
1101    pub value: String,
1102    /// Positional info.
1103    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1104    pub position: Option<Position>,
1105    /// Optional language identifier parsed from an inline code prefix.
1106    ///
1107    /// This is a Socketry Markdown extension; standard mdast inline code
1108    /// nodes do not have a language field.
1109    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1110    pub lang: Option<String>,
1111}
1112
1113/// Math (phrasing).
1114///
1115/// ```markdown
1116/// > | $a$
1117///     ^^^
1118/// ```
1119#[derive(Clone, Debug, Eq, PartialEq)]
1120#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1121pub struct InlineMath {
1122    // Text.
1123    /// Content model.
1124    pub value: String,
1125    /// Positional info.
1126    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1127    pub position: Option<Position>,
1128}
1129
1130/// Break.
1131///
1132/// ```markdown
1133/// > | a\
1134///      ^
1135///   | b
1136/// ```
1137#[derive(Clone, Debug, Eq, PartialEq)]
1138#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1139pub struct Break {
1140    // Void.
1141    /// Positional info.
1142    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1143    pub position: Option<Position>,
1144}
1145
1146/// Link.
1147///
1148/// ```markdown
1149/// > | [a](b)
1150///     ^^^^^^
1151/// ```
1152#[derive(Clone, Debug, Eq, PartialEq)]
1153#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1154pub struct Link {
1155    // Parent.
1156    /// Content model.
1157    pub children: Vec<Node>,
1158    /// Positional info.
1159    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1160    pub position: Option<Position>,
1161    // Resource.
1162    /// URL to the referenced resource.
1163    pub url: String,
1164    /// Advisory info for the resource, such as something that would be
1165    /// appropriate for a tooltip.
1166    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1167    pub title: Option<String>,
1168}
1169
1170/// Image.
1171///
1172/// ```markdown
1173/// > | ![a](b)
1174///     ^^^^^^^
1175/// ```
1176#[derive(Clone, Debug, Eq, PartialEq)]
1177#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1178pub struct Image {
1179    // Void.
1180    /// Positional info.
1181    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1182    pub position: Option<Position>,
1183    // Alternative.
1184    /// Equivalent content for environments that cannot represent the node as
1185    /// intended.
1186    pub alt: String,
1187    // Resource.
1188    /// URL to the referenced resource.
1189    pub url: String,
1190    /// Advisory info for the resource, such as something that would be
1191    /// appropriate for a tooltip.
1192    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1193    pub title: Option<String>,
1194}
1195
1196/// Link reference.
1197///
1198/// ```markdown
1199/// > | [a]
1200///     ^^^
1201/// ```
1202#[derive(Clone, Debug, Eq, PartialEq)]
1203#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1204pub struct LinkReference {
1205    // Parent.
1206    /// Content model.
1207    pub children: Vec<Node>,
1208    /// Positional info.
1209    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1210    pub position: Option<Position>,
1211    // Reference.
1212    /// Explicitness of a reference.
1213    #[cfg_attr(feature = "serde", serde(rename = "referenceType"))]
1214    pub reference_kind: ReferenceKind,
1215    // Association.
1216    /// Value that can match another node.
1217    /// `identifier` is a source value: character escapes and character references
1218    /// are *not* parsed.
1219    /// Its value must be normalized.
1220    pub identifier: String,
1221    /// `label` is a string value: it works just like `title` on a link or a
1222    /// `lang` on code: character escapes and character references are parsed.
1223    ///
1224    /// To normalize a value, collapse markdown whitespace (`[\t\n\r ]+`) to a
1225    /// space, trim the optional initial and/or final space, and perform
1226    /// case-folding.
1227    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1228    pub label: Option<String>,
1229}
1230
1231/// Image reference.
1232///
1233/// ```markdown
1234/// > | ![a]
1235///     ^^^^
1236/// ```
1237#[derive(Clone, Debug, Eq, PartialEq)]
1238#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1239pub struct ImageReference {
1240    // Void.
1241    /// Positional info.
1242    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1243    pub position: Option<Position>,
1244    // Alternative.
1245    /// Equivalent content for environments that cannot represent the node as
1246    /// intended.
1247    pub alt: String,
1248    // Reference.
1249    /// Explicitness of a reference.
1250    #[cfg_attr(feature = "serde", serde(rename = "referenceType"))]
1251    pub reference_kind: ReferenceKind,
1252    // Association.
1253    /// Value that can match another node.
1254    /// `identifier` is a source value: character escapes and character references
1255    /// are *not* parsed.
1256    /// Its value must be normalized.
1257    pub identifier: String,
1258    /// `label` is a string value: it works just like `title` on a link or a
1259    /// `lang` on code: character escapes and character references are parsed.
1260    ///
1261    /// To normalize a value, collapse markdown whitespace (`[\t\n\r ]+`) to a
1262    /// space, trim the optional initial and/or final space, and perform
1263    /// case-folding.
1264    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1265    pub label: Option<String>,
1266}
1267
1268/// GFM: footnote definition.
1269///
1270/// ```markdown
1271/// > | [^a]: b
1272///     ^^^^^^^
1273/// ```
1274#[derive(Clone, Debug, Eq, PartialEq)]
1275#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1276pub struct FootnoteDefinition {
1277    // Parent.
1278    /// Content model.
1279    pub children: Vec<Node>,
1280    /// Positional info.
1281    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1282    pub position: Option<Position>,
1283    // Association.
1284    /// Value that can match another node.
1285    /// `identifier` is a source value: character escapes and character references
1286    /// are *not* parsed.
1287    /// Its value must be normalized.
1288    pub identifier: String,
1289    /// `label` is a string value: it works just like `title` on a link or a
1290    /// `lang` on code: character escapes and character references are parsed.
1291    ///
1292    /// To normalize a value, collapse markdown whitespace (`[\t\n\r ]+`) to a
1293    /// space, trim the optional initial and/or final space, and perform
1294    /// case-folding.
1295    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1296    pub label: Option<String>,
1297}
1298
1299/// GFM: footnote reference.
1300///
1301/// ```markdown
1302/// > | [^a]
1303///     ^^^^
1304/// ```
1305#[derive(Clone, Debug, Eq, PartialEq)]
1306#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1307pub struct FootnoteReference {
1308    // Void.
1309    /// Positional info.
1310    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1311    pub position: Option<Position>,
1312    // Association.
1313    /// Value that can match another node.
1314    /// `identifier` is a source value: character escapes and character references
1315    /// are *not* parsed.
1316    /// Its value must be normalized.
1317    pub identifier: String,
1318    /// `label` is a string value: it works just like `title` on a link or a
1319    /// `lang` on code: character escapes and character references are parsed.
1320    ///
1321    /// To normalize a value, collapse markdown whitespace (`[\t\n\r ]+`) to a
1322    /// space, trim the optional initial and/or final space, and perform
1323    /// case-folding.
1324    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1325    pub label: Option<String>,
1326}
1327
1328/// GFM: table.
1329///
1330/// ```markdown
1331/// > | | a |
1332///     ^^^^^
1333/// > | | - |
1334///     ^^^^^
1335/// ```
1336#[derive(Clone, Debug, Eq, PartialEq)]
1337#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1338pub struct Table {
1339    // Parent.
1340    /// Content model.
1341    pub children: Vec<Node>,
1342    /// Positional info.
1343    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1344    pub position: Option<Position>,
1345    // Extra.
1346    /// Represents how cells in columns are aligned.
1347    pub align: Vec<AlignKind>,
1348}
1349
1350/// GFM: table row.
1351///
1352/// ```markdown
1353/// > | | a |
1354///     ^^^^^
1355/// ```
1356#[derive(Clone, Debug, Eq, PartialEq)]
1357#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1358pub struct TableRow {
1359    // Parent.
1360    /// Content model.
1361    pub children: Vec<Node>,
1362    /// Positional info.
1363    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1364    pub position: Option<Position>,
1365}
1366
1367/// GFM: table cell.
1368///
1369/// ```markdown
1370/// > | | a |
1371///     ^^^^^
1372/// ```
1373#[derive(Clone, Debug, Eq, PartialEq)]
1374#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1375pub struct TableCell {
1376    // Parent.
1377    /// Content model.
1378    pub children: Vec<Node>,
1379    /// Positional info.
1380    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1381    pub position: Option<Position>,
1382}
1383
1384/// GFM: delete.
1385///
1386/// ```markdown
1387/// > | ~~a~~
1388///     ^^^^^
1389/// ```
1390#[derive(Clone, Debug, Eq, PartialEq)]
1391#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1392pub struct Delete {
1393    // Parent.
1394    /// Content model.
1395    pub children: Vec<Node>,
1396    /// Positional info.
1397    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1398    pub position: Option<Position>,
1399}
1400
1401/// Frontmatter: yaml.
1402///
1403/// ```markdown
1404/// > | ---
1405///     ^^^
1406/// > | a: b
1407///     ^^^^
1408/// > | ---
1409///     ^^^
1410/// ```
1411#[derive(Clone, Debug, Eq, PartialEq)]
1412#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1413pub struct Yaml {
1414    // Void.
1415    /// Content model.
1416    pub value: String,
1417    /// Positional info.
1418    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1419    pub position: Option<Position>,
1420}
1421
1422/// Frontmatter: toml.
1423///
1424/// ```markdown
1425/// > | +++
1426///     ^^^
1427/// > | a: b
1428///     ^^^^
1429/// > | +++
1430///     ^^^
1431/// ```
1432#[derive(Clone, Debug, Eq, PartialEq)]
1433#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1434pub struct Toml {
1435    // Void.
1436    /// Content model.
1437    pub value: String,
1438    /// Positional info.
1439    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1440    pub position: Option<Position>,
1441}
1442
1443/// MDX: ESM.
1444///
1445/// ```markdown
1446/// > | import a from 'b'
1447///     ^^^^^^^^^^^^^^^^^
1448/// ```
1449#[derive(Clone, Debug, Eq, PartialEq)]
1450#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1451pub struct MdxjsEsm {
1452    // Literal.
1453    /// Content model.
1454    pub value: String,
1455    /// Positional info.
1456    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1457    pub position: Option<Position>,
1458
1459    // Custom data on where each slice of `value` came from.
1460    #[cfg_attr(feature = "serde", serde(rename = "_markdownRsStops"))]
1461    pub stops: Vec<Stop>,
1462}
1463
1464/// MDX: expression (flow).
1465///
1466/// ```markdown
1467/// > | {a}
1468///     ^^^
1469/// ```
1470#[derive(Clone, Debug, Eq, PartialEq)]
1471#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1472pub struct MdxFlowExpression {
1473    // Literal.
1474    /// Content model.
1475    pub value: String,
1476    /// Positional info.
1477    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1478    pub position: Option<Position>,
1479
1480    // Custom data on where each slice of `value` came from.
1481    #[cfg_attr(feature = "serde", serde(rename = "_markdownRsStops"))]
1482    pub stops: Vec<Stop>,
1483}
1484
1485/// MDX: expression (text).
1486///
1487/// ```markdown
1488/// > | a {b}
1489///       ^^^
1490/// ```
1491#[derive(Clone, Debug, Eq, PartialEq)]
1492#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1493pub struct MdxTextExpression {
1494    // Literal.
1495    /// Content model.
1496    pub value: String,
1497    /// Positional info.
1498    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1499    pub position: Option<Position>,
1500
1501    // Custom data on where each slice of `value` came from.
1502    #[cfg_attr(feature = "serde", serde(rename = "_markdownRsStops"))]
1503    pub stops: Vec<Stop>,
1504}
1505
1506/// MDX: JSX element (container).
1507///
1508/// ```markdown
1509/// > | <a />
1510///     ^^^^^
1511/// ```
1512#[derive(Clone, Debug, Eq, PartialEq)]
1513#[cfg_attr(
1514    feature = "serde",
1515    derive(serde::Serialize, serde::Deserialize),
1516    serde(rename_all = "camelCase")
1517)]
1518pub struct MdxJsxFlowElement {
1519    // Parent.
1520    /// Content model.
1521    pub children: Vec<Node>,
1522    /// Positional info.
1523    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1524    pub position: Option<Position>,
1525    // JSX element.
1526    /// Name.
1527    ///
1528    /// Fragments have no name.
1529    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1530    pub name: Option<String>,
1531    /// Attributes.
1532    pub attributes: Vec<AttributeContent>,
1533}
1534
1535/// MDX: JSX element (text).
1536///
1537/// ```markdown
1538/// > | <a />.
1539///     ^^^^^
1540/// ```
1541#[derive(Clone, Debug, Eq, PartialEq)]
1542#[cfg_attr(
1543    feature = "serde",
1544    derive(serde::Serialize, serde::Deserialize),
1545    serde(rename_all = "camelCase")
1546)]
1547pub struct MdxJsxTextElement {
1548    // Parent.
1549    /// Content model.
1550    pub children: Vec<Node>,
1551    /// Positional info.
1552    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1553    pub position: Option<Position>,
1554    // JSX element.
1555    /// Name.
1556    ///
1557    /// Fragments have no name.
1558    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1559    pub name: Option<String>,
1560    /// Attributes.
1561    pub attributes: Vec<AttributeContent>,
1562}
1563
1564/// MDX: JSX attribute.
1565///
1566/// ```markdown
1567/// > | <a b />
1568///        ^
1569/// ```
1570#[derive(Clone, Debug, Eq, PartialEq)]
1571#[cfg_attr(
1572    feature = "serde",
1573    derive(serde::Serialize, serde::Deserialize),
1574    serde(tag = "type", rename = "mdxJsxAttribute")
1575)]
1576pub struct MdxJsxAttribute {
1577    // Void.
1578    /// Positional info.
1579    // pub position: Option<Position>,
1580    /// Key.
1581    pub name: String,
1582    /// Value.
1583    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1584    pub value: Option<AttributeValue>,
1585}
1586
1587/// MDX: JSX expression attribute.
1588///
1589/// ```markdown
1590/// > | <a {...b} />
1591///        ^
1592/// ```
1593#[derive(Clone, Debug, Eq, PartialEq)]
1594#[cfg_attr(
1595    feature = "serde",
1596    derive(serde::Serialize, serde::Deserialize),
1597    serde(tag = "type", rename = "mdxJsxExpressionAttribute")
1598)]
1599pub struct MdxJsxExpressionAttribute {
1600    /// Value.
1601    pub value: String,
1602    /// Stops
1603    #[cfg_attr(feature = "serde", serde(rename = "_markdownRsStops"))]
1604    pub stops: Vec<Stop>,
1605}
1606
1607#[cfg(test)]
1608mod tests {
1609    use super::*;
1610    use crate::unist::Position;
1611    use alloc::{format, string::ToString, vec};
1612
1613    // Literals.
1614
1615    #[test]
1616    fn text() {
1617        let mut node = Node::Text(Text {
1618            value: "a".into(),
1619            position: None,
1620        });
1621
1622        assert_eq!(
1623            format!("{node:?}"),
1624            "Text { value: \"a\", position: None }",
1625            "should support `Debug`"
1626        );
1627        assert_eq!(node.to_string(), "a", "should support `ToString`");
1628        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1629        assert_eq!(node.children(), None, "should support `children`");
1630        assert_eq!(node.position(), None, "should support `position`");
1631        assert_eq!(node.position_mut(), None, "should support `position`");
1632        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1633        assert_eq!(
1634            format!("{node:?}"),
1635            "Text { value: \"a\", position: Some(1:1-1:2 (0-1)) }",
1636            "should support `position_set`"
1637        );
1638    }
1639
1640    #[test]
1641    fn inline_code() {
1642        let mut node = Node::InlineCode(InlineCode {
1643            value: "a".into(),
1644            position: None,
1645            lang: None,
1646        });
1647
1648        assert_eq!(
1649            format!("{node:?}"),
1650            "InlineCode { value: \"a\", position: None, lang: None }",
1651            "should support `Debug`"
1652        );
1653        assert_eq!(node.to_string(), "a", "should support `ToString`");
1654        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1655        assert_eq!(node.children(), None, "should support `children`");
1656        assert_eq!(node.position(), None, "should support `position`");
1657        assert_eq!(node.position_mut(), None, "should support `position`");
1658        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1659        assert_eq!(
1660            format!("{node:?}"),
1661            "InlineCode { value: \"a\", position: Some(1:1-1:2 (0-1)), lang: None }",
1662            "should support `position_set`"
1663        );
1664    }
1665
1666    #[test]
1667    fn code() {
1668        let mut node = Node::Code(Code {
1669            value: "a".into(),
1670            position: None,
1671            lang: None,
1672            meta: None,
1673        });
1674
1675        assert_eq!(
1676            format!("{node:?}"),
1677            "Code { value: \"a\", position: None, lang: None, meta: None }",
1678            "should support `Debug`"
1679        );
1680        assert_eq!(node.to_string(), "a", "should support `ToString`");
1681        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1682        assert_eq!(node.children(), None, "should support `children`");
1683        assert_eq!(node.position(), None, "should support `position`");
1684        assert_eq!(node.position_mut(), None, "should support `position`");
1685        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1686        assert_eq!(
1687            format!("{node:?}"),
1688            "Code { value: \"a\", position: Some(1:1-1:2 (0-1)), lang: None, meta: None }",
1689            "should support `position_set`"
1690        );
1691    }
1692
1693    #[test]
1694    fn inline_math() {
1695        let mut node = Node::InlineMath(InlineMath {
1696            value: "a".into(),
1697            position: None,
1698        });
1699
1700        assert_eq!(
1701            format!("{node:?}"),
1702            "InlineMath { value: \"a\", position: None }",
1703            "should support `Debug`"
1704        );
1705        assert_eq!(node.to_string(), "a", "should support `ToString`");
1706        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1707        assert_eq!(node.children(), None, "should support `children`");
1708        assert_eq!(node.position(), None, "should support `position`");
1709        assert_eq!(node.position_mut(), None, "should support `position`");
1710        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1711        assert_eq!(
1712            format!("{node:?}"),
1713            "InlineMath { value: \"a\", position: Some(1:1-1:2 (0-1)) }",
1714            "should support `position_set`"
1715        );
1716    }
1717
1718    #[test]
1719    fn math() {
1720        let mut node = Node::Math(Math {
1721            value: "a".into(),
1722            position: None,
1723            meta: None,
1724        });
1725
1726        assert_eq!(
1727            format!("{node:?}"),
1728            "Math { value: \"a\", position: None, meta: None }",
1729            "should support `Debug`"
1730        );
1731        assert_eq!(node.to_string(), "a", "should support `ToString`");
1732        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1733        assert_eq!(node.children(), None, "should support `children`");
1734        assert_eq!(node.position(), None, "should support `position`");
1735        assert_eq!(node.position_mut(), None, "should support `position`");
1736        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1737        assert_eq!(
1738            format!("{node:?}"),
1739            "Math { value: \"a\", position: Some(1:1-1:2 (0-1)), meta: None }",
1740            "should support `position_set`"
1741        );
1742    }
1743
1744    #[test]
1745    fn html() {
1746        let mut node = Node::Html(Html {
1747            value: "a".into(),
1748            position: None,
1749        });
1750
1751        assert_eq!(
1752            format!("{node:?}"),
1753            "Html { value: \"a\", position: None }",
1754            "should support `Debug`"
1755        );
1756        assert_eq!(node.to_string(), "a", "should support `ToString`");
1757        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1758        assert_eq!(node.children(), None, "should support `children`");
1759        assert_eq!(node.position(), None, "should support `position`");
1760        assert_eq!(node.position_mut(), None, "should support `position`");
1761        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1762        assert_eq!(
1763            format!("{node:?}"),
1764            "Html { value: \"a\", position: Some(1:1-1:2 (0-1)) }",
1765            "should support `position_set`"
1766        );
1767    }
1768
1769    #[test]
1770    fn mdx_text_expression() {
1771        let mut node = Node::MdxTextExpression(MdxTextExpression {
1772            value: "a".into(),
1773            stops: vec![],
1774            position: None,
1775        });
1776
1777        assert_eq!(
1778            format!("{node:?}"),
1779            "MdxTextExpression { value: \"a\", position: None, stops: [] }",
1780            "should support `Debug`"
1781        );
1782        assert_eq!(node.to_string(), "a", "should support `ToString`");
1783        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1784        assert_eq!(node.children(), None, "should support `children`");
1785        assert_eq!(node.position(), None, "should support `position`");
1786        assert_eq!(node.position_mut(), None, "should support `position`");
1787        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1788        assert_eq!(
1789            format!("{node:?}"),
1790            "MdxTextExpression { value: \"a\", position: Some(1:1-1:2 (0-1)), stops: [] }",
1791            "should support `position_set`"
1792        );
1793    }
1794
1795    #[test]
1796    fn mdx_flow_expression() {
1797        let mut node = Node::MdxFlowExpression(MdxFlowExpression {
1798            value: "a".into(),
1799            stops: vec![],
1800            position: None,
1801        });
1802
1803        assert_eq!(
1804            format!("{node:?}"),
1805            "MdxFlowExpression { value: \"a\", position: None, stops: [] }",
1806            "should support `Debug`"
1807        );
1808        assert_eq!(node.to_string(), "a", "should support `ToString`");
1809        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1810        assert_eq!(node.children(), None, "should support `children`");
1811        assert_eq!(node.position(), None, "should support `position`");
1812        assert_eq!(node.position_mut(), None, "should support `position`");
1813        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1814        assert_eq!(
1815            format!("{node:?}"),
1816            "MdxFlowExpression { value: \"a\", position: Some(1:1-1:2 (0-1)), stops: [] }",
1817            "should support `position_set`"
1818        );
1819    }
1820
1821    #[test]
1822    fn mdxjs_esm() {
1823        let mut node = Node::MdxjsEsm(MdxjsEsm {
1824            value: "a".into(),
1825            stops: vec![],
1826            position: None,
1827        });
1828
1829        assert_eq!(
1830            format!("{node:?}"),
1831            "MdxjsEsm { value: \"a\", position: None, stops: [] }",
1832            "should support `Debug`"
1833        );
1834        assert_eq!(node.to_string(), "a", "should support `ToString`");
1835        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1836        assert_eq!(node.children(), None, "should support `children`");
1837        assert_eq!(node.position(), None, "should support `position`");
1838        assert_eq!(node.position_mut(), None, "should support `position`");
1839        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1840        assert_eq!(
1841            format!("{node:?}"),
1842            "MdxjsEsm { value: \"a\", position: Some(1:1-1:2 (0-1)), stops: [] }",
1843            "should support `position_set`"
1844        );
1845    }
1846
1847    #[test]
1848    fn toml() {
1849        let mut node = Node::Toml(Toml {
1850            value: "a".into(),
1851            position: None,
1852        });
1853
1854        assert_eq!(
1855            format!("{node:?}"),
1856            "Toml { value: \"a\", position: None }",
1857            "should support `Debug`"
1858        );
1859        assert_eq!(node.to_string(), "a", "should support `ToString`");
1860        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1861        assert_eq!(node.children(), None, "should support `children`");
1862        assert_eq!(node.position(), None, "should support `position`");
1863        assert_eq!(node.position_mut(), None, "should support `position`");
1864        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1865        assert_eq!(
1866            format!("{node:?}"),
1867            "Toml { value: \"a\", position: Some(1:1-1:2 (0-1)) }",
1868            "should support `position_set`"
1869        );
1870    }
1871
1872    #[test]
1873    fn yaml() {
1874        let mut node = Node::Yaml(Yaml {
1875            value: "a".into(),
1876            position: None,
1877        });
1878
1879        assert_eq!(
1880            format!("{node:?}"),
1881            "Yaml { value: \"a\", position: None }",
1882            "should support `Debug`"
1883        );
1884        assert_eq!(node.to_string(), "a", "should support `ToString`");
1885        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1886        assert_eq!(node.children(), None, "should support `children`");
1887        assert_eq!(node.position(), None, "should support `position`");
1888        assert_eq!(node.position_mut(), None, "should support `position`");
1889        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1890        assert_eq!(
1891            format!("{node:?}"),
1892            "Yaml { value: \"a\", position: Some(1:1-1:2 (0-1)) }",
1893            "should support `position_set`"
1894        );
1895    }
1896
1897    // Voids.
1898
1899    #[test]
1900    fn break_node() {
1901        let mut node = Node::Break(Break { position: None });
1902
1903        assert_eq!(
1904            format!("{node:?}"),
1905            "Break { position: None }",
1906            "should support `Debug`"
1907        );
1908        assert_eq!(node.to_string(), "", "should support `ToString`");
1909        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1910        assert_eq!(node.children(), None, "should support `children`");
1911        assert_eq!(node.position(), None, "should support `position`");
1912        assert_eq!(node.position_mut(), None, "should support `position`");
1913        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1914        assert_eq!(
1915            format!("{node:?}"),
1916            "Break { position: Some(1:1-1:2 (0-1)) }",
1917            "should support `position_set`"
1918        );
1919    }
1920
1921    #[test]
1922    fn thematic_break() {
1923        let mut node = Node::ThematicBreak(ThematicBreak { position: None });
1924
1925        assert_eq!(
1926            format!("{node:?}"),
1927            "ThematicBreak { position: None }",
1928            "should support `Debug`"
1929        );
1930        assert_eq!(node.to_string(), "", "should support `ToString`");
1931        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1932        assert_eq!(node.children(), None, "should support `children`");
1933        assert_eq!(node.position(), None, "should support `position`");
1934        assert_eq!(node.position_mut(), None, "should support `position`");
1935        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1936        assert_eq!(
1937            format!("{node:?}"),
1938            "ThematicBreak { position: Some(1:1-1:2 (0-1)) }",
1939            "should support `position_set`"
1940        );
1941    }
1942
1943    #[test]
1944    fn footnote_reference() {
1945        let mut node = Node::FootnoteReference(FootnoteReference {
1946            position: None,
1947            identifier: "a".into(),
1948            label: Some("b".into()),
1949        });
1950
1951        assert_eq!(
1952            format!("{node:?}"),
1953            "FootnoteReference { position: None, identifier: \"a\", label: Some(\"b\") }",
1954            "should support `Debug`"
1955        );
1956        assert_eq!(node.to_string(), "", "should support `ToString`");
1957        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1958        assert_eq!(node.children(), None, "should support `children`");
1959        assert_eq!(node.position(), None, "should support `position`");
1960        assert_eq!(node.position_mut(), None, "should support `position`");
1961        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1962        assert_eq!(
1963            format!("{node:?}"),
1964            "FootnoteReference { position: Some(1:1-1:2 (0-1)), identifier: \"a\", label: Some(\"b\") }",
1965            "should support `position_set`"
1966        );
1967    }
1968
1969    #[test]
1970    fn image_reference() {
1971        let mut node = Node::ImageReference(ImageReference {
1972            position: None,
1973            alt: "a".into(),
1974            identifier: "b".into(),
1975            label: Some("c".into()),
1976            reference_kind: ReferenceKind::Full,
1977        });
1978
1979        assert_eq!(
1980            format!("{node:?}"),
1981            "ImageReference { position: None, alt: \"a\", reference_kind: Full, identifier: \"b\", label: Some(\"c\") }",
1982            "should support `Debug`"
1983        );
1984        assert_eq!(node.to_string(), "", "should support `ToString`");
1985        assert_eq!(node.children_mut(), None, "should support `children_mut`");
1986        assert_eq!(node.children(), None, "should support `children`");
1987        assert_eq!(node.position(), None, "should support `position`");
1988        assert_eq!(node.position_mut(), None, "should support `position`");
1989        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
1990        assert_eq!(
1991            format!("{node:?}"),
1992            "ImageReference { position: Some(1:1-1:2 (0-1)), alt: \"a\", reference_kind: Full, identifier: \"b\", label: Some(\"c\") }",
1993            "should support `position_set`"
1994        );
1995    }
1996
1997    #[test]
1998    fn image() {
1999        let mut node = Node::Image(Image {
2000            position: None,
2001            alt: "a".into(),
2002            url: "b".into(),
2003            title: None,
2004        });
2005
2006        assert_eq!(
2007            format!("{node:?}"),
2008            "Image { position: None, alt: \"a\", url: \"b\", title: None }",
2009            "should support `Debug`"
2010        );
2011        assert_eq!(node.to_string(), "", "should support `ToString`");
2012        assert_eq!(node.children_mut(), None, "should support `children_mut`");
2013        assert_eq!(node.children(), None, "should support `children`");
2014        assert_eq!(node.position(), None, "should support `position`");
2015        assert_eq!(node.position_mut(), None, "should support `position`");
2016        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2017        assert_eq!(
2018            format!("{node:?}"),
2019            "Image { position: Some(1:1-1:2 (0-1)), alt: \"a\", url: \"b\", title: None }",
2020            "should support `position_set`"
2021        );
2022    }
2023
2024    #[test]
2025    fn definition() {
2026        let mut node = Node::Definition(Definition {
2027            position: None,
2028            identifier: "a".into(),
2029            label: None,
2030            url: "b".into(),
2031            title: None,
2032        });
2033
2034        assert_eq!(
2035            format!("{node:?}"),
2036            "Definition { position: None, url: \"b\", title: None, identifier: \"a\", label: None }",
2037            "should support `Debug`"
2038        );
2039        assert_eq!(node.to_string(), "", "should support `ToString`");
2040        assert_eq!(node.children_mut(), None, "should support `children_mut`");
2041        assert_eq!(node.children(), None, "should support `children`");
2042        assert_eq!(node.position(), None, "should support `position`");
2043        assert_eq!(node.position_mut(), None, "should support `position`");
2044        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2045        assert_eq!(
2046            format!("{node:?}"),
2047            "Definition { position: Some(1:1-1:2 (0-1)), url: \"b\", title: None, identifier: \"a\", label: None }",
2048            "should support `position_set`"
2049        );
2050    }
2051
2052    // Parents.
2053
2054    #[test]
2055    fn root() {
2056        let mut node = Node::Root(Root {
2057            position: None,
2058            children: vec![],
2059        });
2060
2061        assert_eq!(
2062            format!("{node:?}"),
2063            "Root { children: [], position: None }",
2064            "should support `Debug`"
2065        );
2066        assert_eq!(node.to_string(), "", "should support `ToString`");
2067        assert_eq!(
2068            node.children_mut(),
2069            Some(&mut vec![]),
2070            "should support `children_mut`"
2071        );
2072        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2073        assert_eq!(node.position(), None, "should support `position`");
2074        assert_eq!(node.position_mut(), None, "should support `position`");
2075        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2076        assert_eq!(
2077            format!("{node:?}"),
2078            "Root { children: [], position: Some(1:1-1:2 (0-1)) }",
2079            "should support `position_set`"
2080        );
2081    }
2082
2083    #[test]
2084    fn block_quote() {
2085        let mut node = Node::Blockquote(Blockquote {
2086            position: None,
2087            children: vec![],
2088        });
2089
2090        assert_eq!(
2091            format!("{node:?}"),
2092            "Blockquote { children: [], position: None }",
2093            "should support `Debug`"
2094        );
2095        assert_eq!(node.to_string(), "", "should support `ToString`");
2096        assert_eq!(
2097            node.children_mut(),
2098            Some(&mut vec![]),
2099            "should support `children_mut`"
2100        );
2101        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2102        assert_eq!(node.position(), None, "should support `position`");
2103        assert_eq!(node.position_mut(), None, "should support `position`");
2104        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2105        assert_eq!(
2106            format!("{node:?}"),
2107            "Blockquote { children: [], position: Some(1:1-1:2 (0-1)) }",
2108            "should support `position_set`"
2109        );
2110    }
2111
2112    #[test]
2113    fn delete() {
2114        let mut node = Node::Delete(Delete {
2115            position: None,
2116            children: vec![],
2117        });
2118
2119        assert_eq!(
2120            format!("{node:?}"),
2121            "Delete { children: [], position: None }",
2122            "should support `Debug`"
2123        );
2124        assert_eq!(node.to_string(), "", "should support `ToString`");
2125        assert_eq!(
2126            node.children_mut(),
2127            Some(&mut vec![]),
2128            "should support `children_mut`"
2129        );
2130        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2131        assert_eq!(node.position(), None, "should support `position`");
2132        assert_eq!(node.position_mut(), None, "should support `position`");
2133        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2134        assert_eq!(
2135            format!("{node:?}"),
2136            "Delete { children: [], position: Some(1:1-1:2 (0-1)) }",
2137            "should support `position_set`"
2138        );
2139    }
2140
2141    #[test]
2142    fn emphasis() {
2143        let mut node = Node::Emphasis(Emphasis {
2144            position: None,
2145            children: vec![],
2146        });
2147
2148        assert_eq!(
2149            format!("{node:?}"),
2150            "Emphasis { children: [], position: None }",
2151            "should support `Debug`"
2152        );
2153        assert_eq!(node.to_string(), "", "should support `ToString`");
2154        assert_eq!(
2155            node.children_mut(),
2156            Some(&mut vec![]),
2157            "should support `children_mut`"
2158        );
2159        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2160        assert_eq!(node.position(), None, "should support `position`");
2161        assert_eq!(node.position_mut(), None, "should support `position`");
2162        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2163        assert_eq!(
2164            format!("{node:?}"),
2165            "Emphasis { children: [], position: Some(1:1-1:2 (0-1)) }",
2166            "should support `position_set`"
2167        );
2168    }
2169
2170    #[test]
2171    fn strong() {
2172        let mut node = Node::Strong(Strong {
2173            position: None,
2174            children: vec![],
2175        });
2176
2177        assert_eq!(
2178            format!("{node:?}"),
2179            "Strong { children: [], position: None }",
2180            "should support `Debug`"
2181        );
2182        assert_eq!(node.to_string(), "", "should support `ToString`");
2183        assert_eq!(
2184            node.children_mut(),
2185            Some(&mut vec![]),
2186            "should support `children_mut`"
2187        );
2188        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2189        assert_eq!(node.position(), None, "should support `position`");
2190        assert_eq!(node.position_mut(), None, "should support `position`");
2191        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2192        assert_eq!(
2193            format!("{node:?}"),
2194            "Strong { children: [], position: Some(1:1-1:2 (0-1)) }",
2195            "should support `position_set`"
2196        );
2197    }
2198
2199    #[test]
2200    fn paragraph() {
2201        let mut node = Node::Paragraph(Paragraph {
2202            position: None,
2203            children: vec![],
2204        });
2205
2206        assert_eq!(
2207            format!("{node:?}"),
2208            "Paragraph { children: [], position: None }",
2209            "should support `Debug`"
2210        );
2211        assert_eq!(node.to_string(), "", "should support `ToString`");
2212        assert_eq!(
2213            node.children_mut(),
2214            Some(&mut vec![]),
2215            "should support `children_mut`"
2216        );
2217        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2218        assert_eq!(node.position(), None, "should support `position`");
2219        assert_eq!(node.position_mut(), None, "should support `position`");
2220        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2221        assert_eq!(
2222            format!("{node:?}"),
2223            "Paragraph { children: [], position: Some(1:1-1:2 (0-1)) }",
2224            "should support `position_set`"
2225        );
2226    }
2227
2228    #[test]
2229    fn table_row() {
2230        let mut node = Node::TableRow(TableRow {
2231            position: None,
2232            children: vec![],
2233        });
2234
2235        assert_eq!(
2236            format!("{node:?}"),
2237            "TableRow { children: [], position: None }",
2238            "should support `Debug`"
2239        );
2240        assert_eq!(node.to_string(), "", "should support `ToString`");
2241        assert_eq!(
2242            node.children_mut(),
2243            Some(&mut vec![]),
2244            "should support `children_mut`"
2245        );
2246        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2247        assert_eq!(node.position(), None, "should support `position`");
2248        assert_eq!(node.position_mut(), None, "should support `position`");
2249        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2250        assert_eq!(
2251            format!("{node:?}"),
2252            "TableRow { children: [], position: Some(1:1-1:2 (0-1)) }",
2253            "should support `position_set`"
2254        );
2255    }
2256
2257    #[test]
2258    fn table_cell() {
2259        let mut node = Node::TableCell(TableCell {
2260            position: None,
2261            children: vec![],
2262        });
2263
2264        assert_eq!(
2265            format!("{node:?}"),
2266            "TableCell { children: [], position: None }",
2267            "should support `Debug`"
2268        );
2269        assert_eq!(node.to_string(), "", "should support `ToString`");
2270        assert_eq!(
2271            node.children_mut(),
2272            Some(&mut vec![]),
2273            "should support `children_mut`"
2274        );
2275        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2276        assert_eq!(node.position(), None, "should support `position`");
2277        assert_eq!(node.position_mut(), None, "should support `position`");
2278        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2279        assert_eq!(
2280            format!("{node:?}"),
2281            "TableCell { children: [], position: Some(1:1-1:2 (0-1)) }",
2282            "should support `position_set`"
2283        );
2284    }
2285
2286    #[test]
2287    fn heading() {
2288        let mut node = Node::Heading(Heading {
2289            position: None,
2290            depth: 1,
2291            children: vec![],
2292        });
2293
2294        assert_eq!(
2295            format!("{node:?}"),
2296            "Heading { children: [], position: None, depth: 1 }",
2297            "should support `Debug`"
2298        );
2299        assert_eq!(node.to_string(), "", "should support `ToString`");
2300        assert_eq!(
2301            node.children_mut(),
2302            Some(&mut vec![]),
2303            "should support `children_mut`"
2304        );
2305        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2306        assert_eq!(node.position(), None, "should support `position`");
2307        assert_eq!(node.position_mut(), None, "should support `position`");
2308        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2309        assert_eq!(
2310            format!("{node:?}"),
2311            "Heading { children: [], position: Some(1:1-1:2 (0-1)), depth: 1 }",
2312            "should support `position_set`"
2313        );
2314    }
2315
2316    #[test]
2317    fn table() {
2318        let mut node = Node::Table(Table {
2319            position: None,
2320            align: vec![],
2321            children: vec![],
2322        });
2323
2324        assert_eq!(
2325            format!("{node:?}"),
2326            "Table { children: [], position: None, align: [] }",
2327            "should support `Debug`"
2328        );
2329        assert_eq!(node.to_string(), "", "should support `ToString`");
2330        assert_eq!(
2331            node.children_mut(),
2332            Some(&mut vec![]),
2333            "should support `children_mut`"
2334        );
2335        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2336        assert_eq!(node.position(), None, "should support `position`");
2337        assert_eq!(node.position_mut(), None, "should support `position`");
2338        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2339        assert_eq!(
2340            format!("{node:?}"),
2341            "Table { children: [], position: Some(1:1-1:2 (0-1)), align: [] }",
2342            "should support `position_set`"
2343        );
2344    }
2345
2346    #[test]
2347    fn list_item() {
2348        let mut node = Node::ListItem(ListItem {
2349            position: None,
2350            spread: false,
2351            checked: None,
2352            children: vec![],
2353        });
2354
2355        assert_eq!(
2356            format!("{node:?}"),
2357            "ListItem { children: [], position: None, spread: false, checked: None }",
2358            "should support `Debug`"
2359        );
2360        assert_eq!(node.to_string(), "", "should support `ToString`");
2361        assert_eq!(
2362            node.children_mut(),
2363            Some(&mut vec![]),
2364            "should support `children_mut`"
2365        );
2366        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2367        assert_eq!(node.position(), None, "should support `position`");
2368        assert_eq!(node.position_mut(), None, "should support `position`");
2369        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2370        assert_eq!(
2371            format!("{node:?}"),
2372            "ListItem { children: [], position: Some(1:1-1:2 (0-1)), spread: false, checked: None }",
2373            "should support `position_set`"
2374        );
2375    }
2376
2377    #[test]
2378    fn list() {
2379        let mut node = Node::List(List {
2380            position: None,
2381            spread: false,
2382            ordered: false,
2383            start: None,
2384            children: vec![],
2385        });
2386
2387        assert_eq!(
2388            format!("{node:?}"),
2389            "List { children: [], position: None, ordered: false, start: None, spread: false }",
2390            "should support `Debug`"
2391        );
2392        assert_eq!(node.to_string(), "", "should support `ToString`");
2393        assert_eq!(
2394            node.children_mut(),
2395            Some(&mut vec![]),
2396            "should support `children_mut`"
2397        );
2398        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2399        assert_eq!(node.position(), None, "should support `position`");
2400        assert_eq!(node.position_mut(), None, "should support `position`");
2401        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2402        assert_eq!(
2403            format!("{node:?}"),
2404            "List { children: [], position: Some(1:1-1:2 (0-1)), ordered: false, start: None, spread: false }",
2405            "should support `position_set`"
2406        );
2407    }
2408
2409    #[test]
2410    fn link_reference() {
2411        let mut node = Node::LinkReference(LinkReference {
2412            position: None,
2413            identifier: "a".into(),
2414            label: None,
2415            reference_kind: ReferenceKind::Full,
2416            children: vec![],
2417        });
2418
2419        assert_eq!(
2420            format!("{node:?}"),
2421            "LinkReference { children: [], position: None, reference_kind: Full, identifier: \"a\", label: None }",
2422            "should support `Debug`"
2423        );
2424        assert_eq!(node.to_string(), "", "should support `ToString`");
2425        assert_eq!(
2426            node.children_mut(),
2427            Some(&mut vec![]),
2428            "should support `children_mut`"
2429        );
2430        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2431        assert_eq!(node.position(), None, "should support `position`");
2432        assert_eq!(node.position_mut(), None, "should support `position`");
2433        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2434        assert_eq!(
2435            format!("{node:?}"),
2436            "LinkReference { children: [], position: Some(1:1-1:2 (0-1)), reference_kind: Full, identifier: \"a\", label: None }",
2437            "should support `position_set`"
2438        );
2439    }
2440
2441    #[test]
2442    fn link() {
2443        let mut node = Node::Link(Link {
2444            position: None,
2445            url: "a".into(),
2446            title: None,
2447            children: vec![],
2448        });
2449
2450        assert_eq!(
2451            format!("{node:?}"),
2452            "Link { children: [], position: None, url: \"a\", title: None }",
2453            "should support `Debug`"
2454        );
2455        assert_eq!(node.to_string(), "", "should support `ToString`");
2456        assert_eq!(
2457            node.children_mut(),
2458            Some(&mut vec![]),
2459            "should support `children_mut`"
2460        );
2461        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2462        assert_eq!(node.position(), None, "should support `position`");
2463        assert_eq!(node.position_mut(), None, "should support `position`");
2464        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2465        assert_eq!(
2466            format!("{node:?}"),
2467            "Link { children: [], position: Some(1:1-1:2 (0-1)), url: \"a\", title: None }",
2468            "should support `position_set`"
2469        );
2470    }
2471
2472    #[test]
2473    fn footnote_definition() {
2474        let mut node = Node::FootnoteDefinition(FootnoteDefinition {
2475            position: None,
2476            identifier: "a".into(),
2477            label: None,
2478            children: vec![],
2479        });
2480
2481        assert_eq!(
2482            format!("{node:?}"),
2483            "FootnoteDefinition { children: [], position: None, identifier: \"a\", label: None }",
2484            "should support `Debug`"
2485        );
2486        assert_eq!(node.to_string(), "", "should support `ToString`");
2487        assert_eq!(
2488            node.children_mut(),
2489            Some(&mut vec![]),
2490            "should support `children_mut`"
2491        );
2492        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2493        assert_eq!(node.position(), None, "should support `position`");
2494        assert_eq!(node.position_mut(), None, "should support `position`");
2495        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2496        assert_eq!(
2497            format!("{node:?}"),
2498            "FootnoteDefinition { children: [], position: Some(1:1-1:2 (0-1)), identifier: \"a\", label: None }",
2499            "should support `position_set`"
2500        );
2501    }
2502
2503    #[test]
2504    fn mdx_jsx_flow_element() {
2505        let mut node = Node::MdxJsxFlowElement(MdxJsxFlowElement {
2506            position: None,
2507            name: None,
2508            attributes: vec![],
2509            children: vec![],
2510        });
2511
2512        assert_eq!(
2513            format!("{node:?}"),
2514            "MdxJsxFlowElement { children: [], position: None, name: None, attributes: [] }",
2515            "should support `Debug`"
2516        );
2517        assert_eq!(node.to_string(), "", "should support `ToString`");
2518        assert_eq!(
2519            node.children_mut(),
2520            Some(&mut vec![]),
2521            "should support `children_mut`"
2522        );
2523        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2524        assert_eq!(node.position(), None, "should support `position`");
2525        assert_eq!(node.position_mut(), None, "should support `position`");
2526        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2527        assert_eq!(
2528            format!("{node:?}"),
2529            "MdxJsxFlowElement { children: [], position: Some(1:1-1:2 (0-1)), name: None, attributes: [] }",
2530            "should support `position_set`"
2531        );
2532    }
2533
2534    #[test]
2535    fn mdx_jsx_text_element() {
2536        let mut node = Node::MdxJsxTextElement(MdxJsxTextElement {
2537            position: None,
2538            name: None,
2539            attributes: vec![],
2540            children: vec![],
2541        });
2542
2543        assert_eq!(
2544            format!("{node:?}"),
2545            "MdxJsxTextElement { children: [], position: None, name: None, attributes: [] }",
2546            "should support `Debug`"
2547        );
2548        assert_eq!(node.to_string(), "", "should support `ToString`");
2549        assert_eq!(
2550            node.children_mut(),
2551            Some(&mut vec![]),
2552            "should support `children_mut`"
2553        );
2554        assert_eq!(node.children(), Some(&vec![]), "should support `children`");
2555        assert_eq!(node.position(), None, "should support `position`");
2556        assert_eq!(node.position_mut(), None, "should support `position`");
2557        node.position_set(Some(Position::new(1, 1, 0, 1, 2, 1)));
2558        assert_eq!(
2559            format!("{node:?}"),
2560            "MdxJsxTextElement { children: [], position: Some(1:1-1:2 (0-1)), name: None, attributes: [] }",
2561            "should support `position_set`"
2562        );
2563    }
2564}