1use once_cell::sync::Lazy;
2
3
4#[test]
5fn title_example() {
6 let parser = &mut markdown_it::MarkdownIt::new();
7 markdown_it::plugins::cmark::add(parser);
8
9 let ast = parser.parse("Hello **world**!");
10 let html = ast.render();
11
12 assert_eq!(html, "<p>Hello <strong>world</strong>!</p>\n");
13}
14
15#[test]
16fn lazy_singleton() {
17 static MD : Lazy<markdown_it::MarkdownIt> = Lazy::new(|| {
18 let mut parser = markdown_it::MarkdownIt::new();
19 markdown_it::plugins::cmark::add(&mut parser);
20 parser
21 });
22
23 let ast = MD.parse("Hello **world**!");
24 let html = ast.render();
25
26 assert_eq!(html, "<p>Hello <strong>world</strong>!</p>\n");
27}
28
29#[test]
30fn no_plugins() {
31 let md = &mut markdown_it::MarkdownIt::new();
32 let node = md.parse("hello\nworld");
33 let result = node.render();
34 assert_eq!(result, "hello\nworld\n");
35}
36
37#[test]
38fn no_max_indent() {
39 let md = &mut markdown_it::MarkdownIt::new();
40 markdown_it::plugins::cmark::block::paragraph::add(md);
41 markdown_it::plugins::cmark::block::list::add(md);
42 md.max_indent = i32::MAX;
43 let node = md.parse(" paragraph\n - item");
44 let result = node.render();
45 assert_eq!(result, "<p>paragraph</p>\n<ul>\n<li>item</li>\n</ul>\n");
46}
47
48
49/*#[test]
50fn no_block_parser() {
51 let md = &mut markdown_it::MarkdownIt::new();
52 markdown_it::plugins::cmark::add(md);
53 md.remove_rule::<markdown_it::parser::block::builtin::BlockParserRule>();
54 let node = md.parse("hello *world*");
55 let result = node.render();
56 assert_eq!(result, "hello <em>world</em>");
57}*/
58
59fn run(input: &str, output: &str) {
60 let output = if output.is_empty() { "".to_owned() } else { output.to_owned() + "\n" };
61 let md = &mut markdown_it::MarkdownIt::new();
62 markdown_it::plugins::cmark::add(md);
63 markdown_it::plugins::html::add(md);
64 markdown_it::plugins::extra::beautify_links::add(md);
65 let node = md.parse(&(input.to_owned() + "\n"));
66 node.walk(|node, _| assert!(node.srcmap.is_some()));
67 let result = node.render();
68 assert_eq!(result, output);
69}
70
71mod markdown_it_rs_extras {
72 use super::run;
73
74 #[test]
75 fn regression_test_img() {
76 // ! at end of line
77 run("Hello!", "<p>Hello!</p>");
78 }
79
80 #[test]
81 fn regression_list_markers() {
82 run("- foo\n- bar", "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>");
83 run("1. foo\n1. bar", "<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>");
84 }
85
86 #[test]
87 fn tab_offset_in_lists() {
88 run(" > -\tfoo\n >\n > foo\n",
89r#"<blockquote>
90<ul>
91<li>
92<p>foo</p>
93<pre><code> foo
94</code></pre>
95</li>
96</ul>
97</blockquote>"#);
98 }
99
100 #[test]
101 fn null_char_replacement() {
102 run("&#0;", "<p>\u{FFFD}</p>");
103 run("\0", "<p>\u{FFFD}</p>");
104 }
105
106 #[test]
107 fn cr_only_newlines() {
108 run("foo\rbar", "<p>foo\nbar</p>");
109 run(" foo\r bar", "<pre><code>foo\nbar\n</code></pre>");
110 }
111
112 #[test]
113 fn cr_lf_newlines() {
114 run("foo\r\nbar", "<p>foo\nbar</p>");
115 run(" foo\r\n bar", "<pre><code>foo\nbar\n</code></pre>");
116 }
117
118 #[test]
119 fn beautify_links() {
120 run("<https://www.reddit.com/r/programming/comments/vxttiq/comment/ifyqsqt/?utm_source=reddit&utm_medium=web2x&context=3>",
121 "<p><a href=\"https://www.reddit.com/r/programming/comments/vxttiq/comment/ifyqsqt/?utm_source=reddit&amp;utm_medium=web2x&amp;context=3\">www.reddit.com/r/programming/comments/…/ifyqsqt/?…</a></p>");
122 }
123
124 #[test]
125 fn regression_test_newlines_with_images() {
126 run("There is a newline in this image ![here\nit is](https://github.com/executablebooks/)",
127 "<p>There is a newline in this image <img src=\"https://github.com/executablebooks/\" alt=\"here\nit is\"></p>");
128 }
129
130 #[test]
131 fn test_node_ext_propagation() {
132 use markdown_it::parser::block::{BlockRule, BlockState};
133 use markdown_it::parser::core::CoreRule;
134 use markdown_it::parser::extset::NodeExt;
135 use markdown_it::parser::inline::{InlineRule, InlineState};
136 use markdown_it::{MarkdownIt, Node};
137
138 #[derive(Debug, Default)]
139 struct NodeErrors(Vec<&'static str>);
140 impl NodeExt for NodeErrors {}
141
142 struct MyInlineRule;
143 impl InlineRule for MyInlineRule {
144 const MARKER: char = '@';
145
146 fn run(state: &mut InlineState) -> Option<(Node, usize)> {
147 let err = state.node.ext.get_or_insert_default::<NodeErrors>();
148 err.0.push("inline");
149 None
150 }
151 }
152
153 struct MyBlockRule;
154 impl BlockRule for MyBlockRule {
155 fn run(state: &mut BlockState) -> Option<(Node, usize)> {
156 let err = state.node.ext.get_or_insert_default::<NodeErrors>();
157 err.0.push("block");
158 None
159 }
160 }
161
162 struct MyCoreRule;
163 impl CoreRule for MyCoreRule {
164 fn run(root: &mut Node, _md: &MarkdownIt) {
165 let err = root.ext.get_or_insert_default::<NodeErrors>();
166 err.0.push("core");
167 }
168 }
169
170 let md = &mut markdown_it::MarkdownIt::new();
171 markdown_it::plugins::cmark::add(md);
172
173 md.inline.add_rule::<MyInlineRule>();
174 md.block.add_rule::<MyBlockRule>();
175 md.add_rule::<MyCoreRule>().after_all();
176
177 let text1 = r#"*hello @world*"#;
178 let ast = md.parse(text1);
179 let mut collected: Vec<&str> = vec![];
180
181 ast.walk_post(|node, _| {
182 if let Some(errors) = node.ext.get::<NodeErrors>() {
183 collected.extend(errors.0.iter());
184 }
185 });
186
187 assert_eq!(
188 collected,
189 vec!["inline", "block", "core"],
190 );
191 }
192}
193
194mod examples {
195 include!("../examples/ferris/main.rs");
196
197 #[test]
198 fn test_examples() {
199 main();
200 }
201}
202