supa_mdx_lint/utils/
mdast.rs

1use markdown::{
2    mdast::{MdxFlowExpression, Node},
3    unist::Position,
4};
5use regex::Regex;
6
7pub trait HasChildren {
8    fn get_children(&self) -> &Vec<Node>;
9}
10
11impl HasChildren for markdown::mdast::Heading {
12    fn get_children(&self) -> &Vec<Node> {
13        &self.children
14    }
15}
16
17impl HasChildren for markdown::mdast::Strong {
18    fn get_children(&self) -> &Vec<Node> {
19        &self.children
20    }
21}
22
23impl HasChildren for markdown::mdast::Emphasis {
24    fn get_children(&self) -> &Vec<Node> {
25        &self.children
26    }
27}
28
29impl HasChildren for markdown::mdast::LinkReference {
30    fn get_children(&self) -> &Vec<Node> {
31        &self.children
32    }
33}
34
35impl HasChildren for markdown::mdast::Link {
36    fn get_children(&self) -> &Vec<Node> {
37        &self.children
38    }
39}
40
41/// For some reason, `export const .* =` is parsed as a Text node. We need to
42/// this out to prevent running lints on it.
43pub(crate) fn is_export_const(node: &markdown::mdast::Node) -> bool {
44    match node {
45        markdown::mdast::Node::Text(text) => {
46            let regex = Regex::new(r"^export\s+const\s+[a-zA-Z0-9_$-]+\s+=").unwrap();
47            regex.is_match(&text.value)
48        }
49        _ => false,
50    }
51}
52
53pub(crate) trait MaybePosition {
54    fn position(&self) -> Option<&Position>;
55}
56
57impl<T: MaybePosition> MaybePosition for &T {
58    fn position(&self) -> Option<&Position> {
59        (*self).position()
60    }
61}
62
63impl MaybePosition for Node {
64    fn position(&self) -> Option<&Position> {
65        self.position()
66    }
67}
68
69impl MaybePosition for MdxFlowExpression {
70    fn position(&self) -> Option<&Position> {
71        self.position.as_ref()
72    }
73}
74
75pub(crate) trait VariantName {
76    fn variant_name(&self) -> String;
77}
78
79impl<T: VariantName> VariantName for &T {
80    fn variant_name(&self) -> String {
81        (*self).variant_name()
82    }
83}
84
85impl VariantName for Node {
86    fn variant_name(&self) -> String {
87        match self {
88            Node::Root(_) => "Root".to_string(),
89            Node::Blockquote(_) => "Blockquote".to_string(),
90            Node::FootnoteDefinition(_) => "FootnoteDefinition".to_string(),
91            Node::MdxJsxFlowElement(_) => "MdxJsxFlowElement".to_string(),
92            Node::List(_) => "List".to_string(),
93            Node::MdxjsEsm(_) => "MdxjsEsm".to_string(),
94            Node::Toml(_) => "Toml".to_string(),
95            Node::Yaml(_) => "Yaml".to_string(),
96            Node::Break(_) => "Break".to_string(),
97            Node::InlineCode(_) => "InlineCode".to_string(),
98            Node::InlineMath(_) => "InlineMath".to_string(),
99            Node::Delete(_) => "Delete".to_string(),
100            Node::Emphasis(_) => "Emphasis".to_string(),
101            Node::MdxTextExpression(_) => "MdxTextExpression".to_string(),
102            Node::FootnoteReference(_) => "FootnoteReference".to_string(),
103            Node::Html(_) => "Html".to_string(),
104            Node::Image(_) => "Image".to_string(),
105            Node::ImageReference(_) => "ImageReference".to_string(),
106            Node::MdxJsxTextElement(_) => "MdxJsxTextElement".to_string(),
107            Node::Link(_) => "Link".to_string(),
108            Node::LinkReference(_) => "LinkReference".to_string(),
109            Node::Strong(_) => "Strong".to_string(),
110            Node::Text(_) => "Text".to_string(),
111            Node::Code(_) => "Code".to_string(),
112            Node::Math(_) => "Math".to_string(),
113            Node::MdxFlowExpression(_) => "MdxFlowExpression".to_string(),
114            Node::Heading(_) => "Heading".to_string(),
115            Node::Table(_) => "Table".to_string(),
116            Node::ThematicBreak(_) => "ThematicBreak".to_string(),
117            Node::TableRow(_) => "TableRow".to_string(),
118            Node::TableCell(_) => "TableCell".to_string(),
119            Node::ListItem(_) => "ListItem".to_string(),
120            Node::Definition(_) => "Definition".to_string(),
121            Node::Paragraph(_) => "Paragraph".to_string(),
122        }
123    }
124}
125
126impl VariantName for MdxFlowExpression {
127    fn variant_name(&self) -> String {
128        "MdxFlowExpression".to_string()
129    }
130}