1fn run(input: &str, output: &str) {
2 let output = if output.is_empty() {
3 "".to_owned()
4 } else {
5 output.to_owned() + "\n"
6 };
7 let md = &mut markdown_it::MarkdownIt::new();
8 markdown_it::plugins::cmark::add(md);
9 markdown_it::plugins::html::add(md);
10 markdown_it::plugins::extra::linkify::add(md);
11 markdown_it::plugins::extra::typographer::add(md);
12 markdown_it::plugins::extra::smartquotes::add(md);
13 let node = md.parse(&(input.to_owned() + "\n"));
14
15 // make sure we have sourcemaps for everything
16 node.walk(|node, _| assert!(node.srcmap.is_some()));
17
18 let result = node.render();
19 assert_eq!(result, output);
20
21 // make sure it doesn't crash without trailing \n
22 let _ = md.parse(input.trim_end());
23}
24///////////////////////////////////////////////////////////////////////////
25// TESTGEN: fixtures/markdown-it/smartquotes.txt
26#[rustfmt::skip]
27mod fixtures_markdown_it_smartquotes_txt {
28use super::run;
29// this part of the file is auto-generated
30// don't edit it, otherwise your changes might be lost
31#[test]
32fn should_parse_nested_quotes() {
33 let input = r#""foo 'bar' baz"
34
35'foo 'bar' baz'"#;
36 let output = r#"<p>“foo ‘bar’ baz”</p>
37<p>‘foo ‘bar’ baz’</p>"#;
38 run(input, output);
39}
40
41#[test]
42fn should_not_overlap_quotes() {
43 let input = r#"'foo "bar' baz""#;
44 let output = r#"<p>‘foo &quot;bar’ baz&quot;</p>"#;
45 run(input, output);
46}
47
48#[test]
49fn should_match_quotes_on_the_same_level() {
50 let input = r#""foo *bar* baz""#;
51 let output = r#"<p>“foo <em>bar</em> baz”</p>"#;
52 run(input, output);
53}
54
55#[test]
56fn should_handle_adjacent_nested_quotes() {
57 let input = r#"'"double in single"'
58
59"'single in double'""#;
60 let output = r#"<p>‘“double in single”’</p>
61<p>“‘single in double’”</p>"#;
62 run(input, output);
63}
64
65#[test]
66fn should_not_match_quotes_on_different_levels() {
67 let input = r#"*"foo* bar"
68
69"foo *bar"*
70
71*"foo* bar *baz"*"#;
72 let output = r#"<p><em>&quot;foo</em> bar&quot;</p>
73<p>&quot;foo <em>bar&quot;</em></p>
74<p><em>&quot;foo</em> bar <em>baz&quot;</em></p>"#;
75 run(input, output);
76}
77
78#[test]
79fn smartquotes_should_not_overlap_with_other_tags() {
80 let input = r#"*foo "bar* *baz" quux*"#;
81 let output = r#"<p><em>foo &quot;bar</em> <em>baz&quot; quux</em></p>"#;
82 run(input, output);
83}
84
85#[test]
86fn should_try_and_find_matching_quote_in_this_case() {
87 let input = r#""foo "bar 'baz""#;
88 let output = r#"<p>&quot;foo “bar 'baz”</p>"#;
89 run(input, output);
90}
91
92#[test]
93fn should_not_touch_inches_in_quotes() {
94 let input = r#""Monitor 21"" and "Monitor"""#;
95 let output = r#"<p>“Monitor 21&quot;” and “Monitor”&quot;</p>"#;
96 run(input, output);
97}
98
99#[test]
100fn should_render_an_apostrophe_as_a_rsquo() {
101 let input = r#"This isn't and can't be the best approach to implement this..."#;
102 let output = r#"<p>This isn’t and can’t be the best approach to implement this…</p>"#;
103 run(input, output);
104}
105
106#[test]
107fn apostrophe_could_end_the_word_that_s_why_original_smartypants_replaces_all_of_them_as_rsquo() {
108 let input = r#"users' stuff"#;
109 let output = r#"<p>users’ stuff</p>"#;
110 run(input, output);
111}
112
113#[test]
114fn quotes_between_punctuation_chars() {
115 let input = r#""(hai)"."#;
116 let output = r#"<p>“(hai)”.</p>"#;
117 run(input, output);
118}
119
120#[test]
121fn quotes_at_the_start_end_of_the_tokens() {
122 let input = r#""*foo* bar"
123
124"foo *bar*"
125
126"*foo bar*""#;
127 let output = r#"<p>“<em>foo</em> bar”</p>
128<p>“foo <em>bar</em>”</p>
129<p>“<em>foo bar</em>”</p>"#;
130 run(input, output);
131}
132
133#[test]
134fn should_treat_softbreak_as_a_space() {
135 let input = r#""this"
136and "that".
137
138"this" and
139"that"."#;
140 let output = r#"<p>“this”
141and “that”.</p>
142<p>“this” and
143“that”.</p>"#;
144 run(input, output);
145}
146
147#[test]
148fn should_treat_hardbreak_as_a_space() {
149 let input = r#""this"\
150and "that".
151
152"this" and\
153"that"."#;
154 let output = r#"<p>“this”<br>
155and “that”.</p>
156<p>“this” and<br>
157“that”.</p>"#;
158 run(input, output);
159}
160
161#[test]
162fn should_allow_quotes_adjacent_to_other_punctuation_characters_643() {
163 let input = r#"The dog---"'man's' best friend""#;
164 let output = r#"<p>The dog—“‘man’s’ best friend”</p>"#;
165 run(input, output);
166}
167
168#[test]
169fn should_parse_quotes_adjacent_to_code_block_677() {
170 let input = r#""test `code`"
171
172"`code` test""#;
173 let output = r#"<p>“test <code>code</code>”</p>
174<p>“<code>code</code> test”</p>"#;
175 run(input, output);
176}
177
178#[test]
179fn should_parse_quotes_adjacent_to_inline_html_677() {
180 let input = r#""test <br>"
181
182"<br> test""#;
183 let output = r#"<p>“test <br>”</p>
184<p>“<br> test”</p>"#;
185 run(input, output);
186}
187
188#[test]
189fn should_be_escapable() {
190 let input = r#""foo"
191
192\"foo"
193
194"foo\""#;
195 let output = r#"<p>“foo”</p>
196<p>&quot;foo&quot;</p>
197<p>&quot;foo&quot;</p>"#;
198 run(input, output);
199}
200
201#[test]
202fn should_not_replace_entities() {
203 let input = r#"&quot;foo&quot;
204
205&quot;foo"
206
207"foo&quot;"#;
208 let output = r#"<p>&quot;foo&quot;</p>
209<p>&quot;foo&quot;</p>
210<p>&quot;foo&quot;</p>"#;
211 run(input, output);
212}
213// end of auto-generated module
214}