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