1pub mod alerts;
8pub mod ast;
9pub mod attributes;
10pub mod block_quotes;
11pub mod blocks;
12pub mod chunk_options;
13pub mod citations;
14pub mod code_blocks;
15pub mod crossrefs;
16pub mod definitions;
17pub mod fenced_divs;
18pub mod headings;
19pub mod inlines;
20pub mod json;
21pub mod kind;
22pub mod links;
23pub mod lists;
24pub mod math;
25pub mod raw_tex;
26pub mod references;
27pub mod shortcodes;
28pub mod tables;
29pub mod yaml;
30
31pub use alerts::*;
32pub use ast::*;
33pub use attributes::*;
34pub use block_quotes::*;
35pub use blocks::*;
36pub use chunk_options::*;
37pub use citations::*;
38pub use code_blocks::*;
39pub use crossrefs::*;
40pub use definitions::*;
41pub use fenced_divs::*;
42pub use headings::*;
43pub use inlines::*;
44pub use json::*;
45pub use kind::*;
46pub use links::*;
47pub use lists::*;
48pub use math::*;
49pub use raw_tex::*;
50pub use references::*;
51pub use shortcodes::*;
52pub use tables::*;
53pub use yaml::*;
54
55pub type SyntaxNode = rowan::SyntaxNode<PanacheLanguage>;
56pub type SyntaxToken = rowan::SyntaxToken<PanacheLanguage>;
57pub type SyntaxElement = rowan::SyntaxElement<PanacheLanguage>;
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_heading_wrapper() {
65 use crate::Config;
66 use crate::parser::parse;
67
68 let input = "# Hello World\n\nParagraph.";
69 let tree = parse(input, Some(Config::default()));
70
71 let heading = tree
72 .children()
73 .find_map(Heading::cast)
74 .expect("should find heading");
75
76 assert_eq!(heading.level(), 1);
77 assert_eq!(heading.text(), "Hello World");
78 }
79
80 #[test]
81 fn test_link_wrapper() {
82 use crate::Config;
83 use crate::parser::parse;
84
85 let input = "Click [here](https://example.com).";
86 let tree = parse(input, Some(Config::default()));
87
88 let link = tree
90 .descendants()
91 .find_map(Link::cast)
92 .expect("should find link");
93
94 assert_eq!(
95 link.text().map(|t| t.text_content()),
96 Some("here".to_string())
97 );
98 assert_eq!(
99 link.dest().map(|d| d.url_content()),
100 Some("https://example.com".to_string())
101 );
102 }
103
104 #[test]
105 fn test_image_wrapper() {
106 use crate::Config;
107 use crate::parser::parse;
108
109 let input = "";
110 let tree = parse(input, Some(Config::default()));
111
112 let image = tree
113 .descendants()
114 .find_map(ImageLink::cast)
115 .expect("should find image");
116
117 assert_eq!(image.alt().map(|a| a.text()), Some("Alt text".to_string()));
118 }
119
120 #[test]
121 fn test_autolink_wrapper() {
122 use crate::Config;
123 use crate::parser::parse;
124
125 let input = "<https://example.com>";
126 let tree = parse(input, Some(Config::default()));
127
128 let autolink = tree
129 .descendants()
130 .find_map(AutoLink::cast)
131 .expect("should find autolink");
132
133 assert_eq!(autolink.target(), "https://example.com");
134 }
135
136 #[test]
137 fn test_shortcode_wrapper() {
138 use crate::Config;
139 use crate::parser::parse;
140
141 let input = "{{< include \"chapters/part 1.qmd\" >}}";
142 let tree = parse(input, Some(Config::default()));
143
144 let shortcode = tree
145 .descendants()
146 .find_map(Shortcode::cast)
147 .expect("should find shortcode");
148
149 assert_eq!(shortcode.name().as_deref(), Some("include"));
150 assert_eq!(
151 shortcode.args(),
152 vec!["include".to_string(), "chapters/part 1.qmd".to_string()]
153 );
154 }
155
156 #[test]
157 fn test_table_wrapper() {
158 use crate::Config;
159 use crate::parser::parse;
160
161 let input = r#"| A | B |
162|---|---|
163| 1 | 2 |
164
165Table: My caption
166"#;
167 let tree = parse(input, Some(Config::default()));
168
169 let table = tree
170 .descendants()
171 .find_map(PipeTable::cast)
172 .expect("should find table");
173
174 assert_eq!(
175 table.caption().map(|c| c.text()),
176 Some("My caption".to_string())
177 );
178 assert!(table.rows().count() > 0);
179 }
180}