Markdown parser fork with extended syntax for personal use.
1use markdown::{
2 mdast::{Code, Node, Root},
3 message, to_html, to_html_with_options, to_mdast,
4 unist::Position,
5 Constructs, Options, ParseOptions,
6};
7use pretty_assertions::assert_eq;
8
9#[test]
10fn code_fenced() -> Result<(), message::Message> {
11 assert_eq!(
12 to_html("```\n<\n >\n```"),
13 "<pre><code><\n >\n</code></pre>",
14 "should support fenced code w/ grave accents"
15 );
16
17 assert_eq!(
18 to_html("~~~\n<\n >\n~~~"),
19 "<pre><code><\n >\n</code></pre>",
20 "should support fenced code w/ tildes"
21 );
22
23 assert_eq!(
24 to_html("``\nfoo\n``"),
25 "<p><code>foo</code></p>",
26 "should not support fenced code w/ less than three markers"
27 );
28
29 assert_eq!(
30 to_html("```\naaa\n~~~\n```"),
31 "<pre><code>aaa\n~~~\n</code></pre>",
32 "should not support a tilde closing sequence for a grave accent opening sequence"
33 );
34
35 assert_eq!(
36 to_html("~~~\naaa\n```\n~~~"),
37 "<pre><code>aaa\n```\n</code></pre>",
38 "should not support a grave accent closing sequence for a tilde opening sequence"
39 );
40
41 assert_eq!(
42 to_html("````\naaa\n```\n``````"),
43 "<pre><code>aaa\n```\n</code></pre>",
44 "should support a closing sequence longer, but not shorter than, the opening"
45 );
46
47 assert_eq!(
48 to_html("~~~~\naaa\n~~~\n~~~~"),
49 "<pre><code>aaa\n~~~\n</code></pre>",
50 "should support a closing sequence equal to, but not shorter than, the opening"
51 );
52
53 assert_eq!(
54 to_html("```"),
55 "<pre><code></code></pre>\n",
56 "should support an eof right after an opening sequence"
57 );
58
59 assert_eq!(
60 to_html("`````\n\n```\naaa\n"),
61 "<pre><code>\n```\naaa\n</code></pre>\n",
62 "should support an eof somewhere in content"
63 );
64
65 assert_eq!(
66 to_html("> ```\n> aaa\n\nbbb"),
67 "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>",
68 "should support no closing sequence in a block quote"
69 );
70
71 assert_eq!(
72 to_html("```\n\n \n```"),
73 "<pre><code>\n \n</code></pre>",
74 "should support blank lines in fenced code"
75 );
76
77 assert_eq!(
78 to_html("```\n```"),
79 "<pre><code></code></pre>",
80 "should support empty fenced code"
81 );
82
83 assert_eq!(
84 to_html(" ```\n aaa\naaa\n```"),
85 "<pre><code>aaa\naaa\n</code></pre>",
86 "should remove up to one space from the content if the opening sequence is indented w/ 1 space"
87 );
88
89 assert_eq!(
90 to_html(" ```\naaa\n aaa\naaa\n ```"),
91 "<pre><code>aaa\naaa\naaa\n</code></pre>",
92 "should remove up to two space from the content if the opening sequence is indented w/ 2 spaces"
93 );
94
95 assert_eq!(
96 to_html(" ```\n aaa\n aaa\n aaa\n ```"),
97 "<pre><code>aaa\n aaa\naaa\n</code></pre>",
98 "should remove up to three space from the content if the opening sequence is indented w/ 3 spaces"
99 );
100
101 assert_eq!(
102 to_html(" ```\n aaa\n ```"),
103 "<pre><code>```\naaa\n```\n</code></pre>",
104 "should not support indenteding the opening sequence w/ 4 spaces"
105 );
106
107 assert_eq!(
108 to_html("```\naaa\n ```"),
109 "<pre><code>aaa\n</code></pre>",
110 "should support an indented closing sequence"
111 );
112
113 assert_eq!(
114 to_html(" ```\naaa\n ```"),
115 "<pre><code>aaa\n</code></pre>",
116 "should support a differently indented closing sequence than the opening sequence"
117 );
118
119 assert_eq!(
120 to_html("```\naaa\n ```\n"),
121 "<pre><code>aaa\n ```\n</code></pre>\n",
122 "should not support an indented closing sequence w/ 4 spaces"
123 );
124
125 assert_eq!(
126 to_html("``` ```\naaa"),
127 "<p><code> </code>\naaa</p>",
128 "should not support grave accents in the opening fence after the opening sequence"
129 );
130
131 assert_eq!(
132 to_html("~~~~~~\naaa\n~~~ ~~\n"),
133 "<pre><code>aaa\n~~~ ~~\n</code></pre>\n",
134 "should not support spaces in the closing sequence"
135 );
136
137 assert_eq!(
138 to_html("foo\n```\nbar\n```\nbaz"),
139 "<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>",
140 "should support interrupting paragraphs"
141 );
142
143 assert_eq!(
144 to_html("foo\n---\n~~~\nbar\n~~~\n# baz"),
145 "<h2>foo</h2>\n<pre><code>bar\n</code></pre>\n<h1>baz</h1>",
146 "should support interrupting other content"
147 );
148
149 assert_eq!(
150 to_html("```ruby\ndef foo(x)\n return 3\nend\n```"),
151 "<pre><code class=\"language-ruby\">def foo(x)\n return 3\nend\n</code></pre>",
152 "should support the info string as a `language-` class (1)"
153 );
154
155 assert_eq!(
156 to_html("````;\n````"),
157 "<pre><code class=\"language-;\"></code></pre>",
158 "should support the info string as a `language-` class (2)"
159 );
160
161 assert_eq!(
162 to_html("~~~~ ruby startline=3 $%@#$\ndef foo(x)\n return 3\nend\n~~~~~~~"),
163 "<pre><code class=\"language-ruby\">def foo(x)\n return 3\nend\n</code></pre>",
164 "should support the info string as a `language-` class, but not the meta string"
165 );
166
167 assert_eq!(
168 to_html("``` aa ```\nfoo"),
169 "<p><code>aa</code>\nfoo</p>",
170 "should not support grave accents in the meta string"
171 );
172
173 assert_eq!(
174 to_html("~~~ aa ``` ~~~\nfoo\n~~~"),
175 "<pre><code class=\"language-aa\">foo\n</code></pre>",
176 "should support grave accents and tildes in the meta string of tilde fenced code"
177 );
178
179 assert_eq!(
180 to_html("```\n``` aaa\n```"),
181 "<pre><code>``` aaa\n</code></pre>",
182 "should not support info string on closing sequences"
183 );
184
185 // Our own:
186 assert_eq!(
187 to_html("``` "),
188 "<pre><code></code></pre>\n",
189 "should support an eof after whitespace, after the start fence sequence"
190 );
191
192 assert_eq!(
193 to_html("``` js\nalert(1)\n```"),
194 "<pre><code class=\"language-js\">alert(1)\n</code></pre>",
195 "should support whitespace between the sequence and the info string"
196 );
197
198 assert_eq!(
199 to_html("```js"),
200 "<pre><code class=\"language-js\"></code></pre>\n",
201 "should support an eof after the info string"
202 );
203
204 assert_eq!(
205 to_html("``` js \nalert(1)\n```"),
206 "<pre><code class=\"language-js\">alert(1)\n</code></pre>",
207 "should support whitespace after the info string"
208 );
209
210 assert_eq!(
211 to_html("```\n "),
212 "<pre><code> \n</code></pre>\n",
213 "should support an eof after whitespace in content"
214 );
215
216 assert_eq!(
217 to_html(" ```\n "),
218 "<pre><code></code></pre>\n",
219 "should support an eof in the prefix, in content"
220 );
221
222 assert_eq!(
223 to_html("```j\\+s©"),
224 "<pre><code class=\"language-j+s©\"></code></pre>\n",
225 "should support character escapes and character references in info strings"
226 );
227
228 assert_eq!(
229 to_html("```a\\&b\0c"),
230 "<pre><code class=\"language-a&b�c\"></code></pre>\n",
231 "should encode dangerous characters in languages"
232 );
233
234 assert_eq!(
235 to_html(" ```\naaa\n ```"),
236 "<pre><code>aaa\n ```\n</code></pre>\n",
237 "should not support a closing sequence w/ too much indent, regardless of opening sequence (1)"
238 );
239
240 assert_eq!(
241 to_html("> ```\n>\n>\n>\n\na"),
242 "<blockquote>\n<pre><code>\n\n\n</code></pre>\n</blockquote>\n<p>a</p>",
243 "should not support a closing sequence w/ too much indent, regardless of opening sequence (2)"
244 );
245
246 assert_eq!(
247 to_html("> ```a\nb"),
248 "<blockquote>\n<pre><code class=\"language-a\"></code></pre>\n</blockquote>\n<p>b</p>",
249 "should not support lazyness (1)"
250 );
251
252 assert_eq!(
253 to_html("> a\n```b"),
254 "<blockquote>\n<p>a</p>\n</blockquote>\n<pre><code class=\"language-b\"></code></pre>\n",
255 "should not support lazyness (2)"
256 );
257
258 assert_eq!(
259 to_html("> ```a\n```"),
260 "<blockquote>\n<pre><code class=\"language-a\"></code></pre>\n</blockquote>\n<pre><code></code></pre>\n",
261 "should not support lazyness (3)"
262 );
263
264 assert_eq!(
265 to_html_with_options(
266 "```",
267 &Options {
268 parse: ParseOptions {
269 constructs: Constructs {
270 code_fenced: false,
271 ..Default::default()
272 },
273 ..Default::default()
274 },
275 ..Default::default()
276 }
277 )?,
278 "<p>```</p>",
279 "should support turning off code (fenced)"
280 );
281
282 assert_eq!(
283 to_mdast(
284 "```js extra\nconsole.log(1)\nconsole.log(2)\n```",
285 &Default::default()
286 )?,
287 Node::Root(Root {
288 children: vec![Node::Code(Code {
289 lang: Some("js".into()),
290 meta: Some("extra".into()),
291 value: "console.log(1)\nconsole.log(2)".into(),
292 position: Some(Position::new(1, 1, 0, 4, 4, 45))
293 })],
294 position: Some(Position::new(1, 1, 0, 4, 4, 45))
295 }),
296 "should support code (fenced) as `Code`s in mdast"
297 );
298
299 assert_eq!(
300 to_mdast("```\nasd", &Default::default())?,
301 Node::Root(Root {
302 children: vec![Node::Code(Code {
303 lang: None,
304 meta: None,
305 value: "asd".into(),
306 position: Some(Position::new(1, 1, 0, 2, 4, 7))
307 })],
308 position: Some(Position::new(1, 1, 0, 2, 4, 7))
309 }),
310 "should support code (fenced) w/o closing fence in mdast"
311 );
312
313 assert_eq!(
314 to_mdast("```\rasd\r```", &Default::default())?,
315 Node::Root(Root {
316 children: vec![Node::Code(Code {
317 lang: None,
318 meta: None,
319 value: "asd".into(),
320 position: Some(Position::new(1, 1, 0, 3, 4, 11))
321 })],
322 position: Some(Position::new(1, 1, 0, 3, 4, 11))
323 }),
324 "should support code (fenced) w/o CR line endings"
325 );
326
327 assert_eq!(
328 to_mdast("```\r\nasd\r\n```", &Default::default())?,
329 Node::Root(Root {
330 children: vec![Node::Code(Code {
331 lang: None,
332 meta: None,
333 value: "asd".into(),
334 position: Some(Position::new(1, 1, 0, 3, 4, 13))
335 })],
336 position: Some(Position::new(1, 1, 0, 3, 4, 13))
337 }),
338 "should support code (fenced) w/o CR+LF line endings"
339 );
340
341 Ok(())
342}