1use markdown_it::Node;
2use markdown_it::common::sourcemap::SourceWithLineStarts;
3
4fn run(input: &str, f: fn (&Node, SourceWithLineStarts)) {
5 let md = &mut markdown_it::MarkdownIt::new();
6 markdown_it::plugins::cmark::add(md);
7 markdown_it::plugins::html::add(md);
8 let node = md.parse(input);
9 node.walk(|node, _| assert!(node.srcmap.is_some()));
10 f(&node, SourceWithLineStarts::new(input));
11}
12
13fn getmap(node: &Node, map: &SourceWithLineStarts) -> ((u32, u32), (u32, u32)) {
14 node.srcmap.unwrap().get_positions(map)
15}
16
17#[test]
18fn paragraph() {
19 // same as commonmark.js
20 run("foo \n \n \n\n barbaz\n\tquux \n", |node, map| {
21 assert_eq!(
22 getmap(&node.children[0], &map),
23 ((1, 1), (1, 6)),
24 );
25 assert_eq!(
26 getmap(&node.children[1], &map),
27 ((5, 3), (6, 8)),
28 );
29 });
30}
31
32#[test]
33fn hr() {
34 // same as commonmark.js
35 run(" --- \n\n * * *\n", |node, map| {
36 assert_eq!(
37 getmap(&node.children[0], &map),
38 ((1, 2), (1, 6)),
39 );
40 assert_eq!(
41 getmap(&node.children[1], &map),
42 ((3, 3), (3, 7)),
43 );
44 });
45}
46
47#[test]
48fn heading() {
49 // same as commonmark.js
50 run(" \n ### foo ### \n\n", |node, map| {
51 assert_eq!(
52 getmap(&node.children[0], &map),
53 ((2, 3), (2, 15)),
54 );
55 });
56
57 run(" #\n", |node, map| {
58 assert_eq!(
59 getmap(&node.children[0], &map),
60 ((1, 3), (1, 3)),
61 );
62 });
63}
64
65#[test]
66fn lheading() {
67 // same as commonmark.js
68 run(" foo\n bar\n ----\n\n", |node, map| {
69 assert_eq!(
70 getmap(&node.children[0], &map),
71 ((1, 3), (3, 5)),
72 );
73 });
74}
75
76#[test]
77fn fence() {
78 // same as commonmark.js
79 run(" ~~~ foo ~~~\n", |node, map| {
80 assert_eq!(
81 getmap(&node.children[0], &map),
82 ((1, 3), (1, 13)),
83 );
84 });
85
86 run(" ```\n 12\n", |node, map| {
87 assert_eq!(
88 getmap(&node.children[0], &map),
89 ((1, 3), (2, 3)),
90 );
91 });
92
93 run("```\n\n\n\n", |node, map| {
94 assert_eq!(
95 getmap(&node.children[0], &map),
96 ((1, 1), (4, 0)),
97 );
98 });
99
100 run("~~~\na\nb\n~~~ \nc\n", |node, map| {
101 assert_eq!(
102 getmap(&node.children[0], &map),
103 ((1, 1), (4, 5)),
104 );
105 });
106}
107
108#[test]
109fn html_block() {
110 // same as commonmark.js
111 run(" <div>\n", |node, map| {
112 assert_eq!(
113 getmap(&node.children[0], &map),
114 ((1, 3), (1, 7)),
115 );
116 });
117
118 run("<div>\n</div> \n", |node, map| {
119 assert_eq!(
120 getmap(&node.children[0], &map),
121 ((1, 1), (2, 8)),
122 );
123 });
124}
125
126#[test]
127fn code_block() {
128 // this should be (1, 5), (1, 9)
129 // for simplicity, we point source maps for block tags to first
130 // nonspace character, but it isn't quite correct for code blocks
131 run(" foo\n", |node, map| {
132 assert_eq!(
133 getmap(&node.children[0], &map),
134 ((1, 7), (1, 9)),
135 );
136 });
137
138 run(" a\n b\n c\n", |node, map| {
139 assert_eq!(
140 getmap(&node.children[0], &map),
141 ((1, 4), (3, 6)),
142 );
143 });
144
145 // this I believe to be error in commonmark, code block
146 // only have 1 line as per spec, but cmark reports 3 lines
147 run(" foobar \n \n \n\nbar\n", |node, map| {
148 assert_eq!(
149 getmap(&node.children[0], &map),
150 ((1, 5), (1, 12)),
151 );
152 });
153}
154
155#[test]
156fn blockquotes() {
157 // same as commonmark.js
158 run(" > foo \n", |node, map| {
159 assert_eq!(
160 getmap(&node.children[0], &map),
161 ((1, 3), (1, 9)),
162 );
163 });
164
165 run("> foo\nbar\n\n", |node, map| {
166 assert_eq!(
167 getmap(&node.children[0], &map),
168 ((1, 1), (2, 3)),
169 );
170 });
171}
172
173#[test]
174fn lists() {
175 // same as commonmark.js
176 run(" 1. foo\n 2. bar\n", |node, map| {
177 assert_eq!(
178 getmap(&node.children[0], &map),
179 ((1, 2), (2, 7)),
180 );
181
182 assert_eq!(
183 getmap(&node.children[0].children[0], &map),
184 ((1, 2), (1, 7)),
185 );
186 });
187
188 run(" - foo\n\n - bar\n", |node, map| {
189 assert_eq!(
190 getmap(&node.children[0], &map),
191 ((1, 2), (3, 6)),
192 );
193
194 assert_eq!(
195 getmap(&node.children[0].children[0], &map),
196 ((1, 2), (2, 0)),
197 );
198
199 assert_eq!(
200 getmap(&node.children[0].children[1], &map),
201 ((3, 2), (3, 6)),
202 );
203 });
204}
205
206#[test]
207fn autolinks() {
208 run("foo <http://google.com> bar", |node, map| {
209 assert_eq!(
210 getmap(&node.children[0].children[1], &map),
211 ((1, 5), (1, 23)),
212 );
213
214 assert_eq!(
215 getmap(&node.children[0].children[1].children[0], &map),
216 ((1, 6), (1, 22)),
217 );
218 });
219}
220
221#[test]
222fn emphasis() {
223 run("***foo***", |node, map| {
224 assert_eq!(
225 getmap(&node.children[0].children[0], &map),
226 ((1, 1), (1, 9)),
227 );
228
229 assert_eq!(
230 getmap(&node.children[0].children[0].children[0], &map),
231 ((1, 2), (1, 8)),
232 );
233 });
234
235 run("aaa **bb _cc_ dd** eee", |node, map| {
236 assert_eq!(
237 getmap(&node.children[0].children[1], &map),
238 ((1, 5), (1, 18)),
239 );
240
241 assert_eq!(
242 getmap(&node.children[0].children[1].children[1], &map),
243 ((1, 10), (1, 13)),
244 );
245 });
246}
247
248#[test]
249fn newline() {
250 run("foo \nbar \nbaz\nquux", |node, map| {
251 assert_eq!(
252 getmap(&node.children[0].children[1], &map),
253 ((1, 4), (2, 0)),
254 );
255
256 assert_eq!(
257 getmap(&node.children[0].children[3], &map),
258 ((2, 4), (3, 0)),
259 );
260
261 assert_eq!(
262 getmap(&node.children[0].children[5], &map),
263 ((4, 0), (4, 0)),
264 );
265
266 /*let marks : Vec<_> = node.children[0].children.iter().map(|x| getmap(x, &map)).collect();
267 assert_eq!(marks, [
268 ((1, 1), (1, 5)),
269 ((2, 0), (2, 1)),
270 ((2, 1), (2, 3)),
271 ((3, 0), (3, 0)),
272 ((3, 1), (3, 3)),
273 ]);*/
274 });
275}
276
277#[test]
278fn escapes() {
279 run("foo\\Δ\\*bar", |node, map| {
280 assert_eq!(
281 getmap(&node.children[0].children[1], &map),
282 ((1, 4), (1, 5)),
283 );
284
285 assert_eq!(
286 getmap(&node.children[0].children[2], &map),
287 ((1, 6), (1, 7)),
288 );
289 });
290
291 run(" foo \\\n bar ", |node, map| {
292 assert_eq!(
293 getmap(&node.children[0].children[1], &map),
294 ((1, 8), (2, 2)),
295 );
296 });
297}
298
299#[test]
300fn entities() {
301 run("aa &nbsp; bb &#20; cc", |node, map| {
302 assert_eq!(
303 getmap(&node.children[0].children[1], &map),
304 ((1, 4), (1, 9)),
305 );
306
307 assert_eq!(
308 getmap(&node.children[0].children[3], &map),
309 ((1, 14), (1, 18)),
310 );
311
312 /*let marks : Vec<_> = node.children[0].children.iter().map(|x| getmap(x, &map)).collect();
313 assert_eq!(marks, [
314 ((1, 1), (1, 5)),
315 ((2, 0), (2, 1)),
316 ((2, 1), (2, 3)),
317 ((3, 0), (3, 0)),
318 ((3, 1), (3, 3)),
319 ]);*/
320 });
321}
322
323#[test]
324fn html_inline() {
325 run("foo <bar> baz", |node, map| {
326 assert_eq!(
327 getmap(&node.children[0].children[1], &map),
328 ((1, 5), (1, 9)),
329 );
330 });
331}
332
333#[test]
334fn backticks() {
335 run("foo ```bar``` baz", |node, map| {
336 assert_eq!(
337 getmap(&node.children[0].children[1], &map),
338 ((1, 5), (1, 13)),
339 );
340
341 assert_eq!(
342 getmap(&node.children[0].children[1].children[0], &map),
343 ((1, 8), (1, 10)),
344 );
345 });
346
347 run("foo ` bar ` baz", |node, map| {
348 assert_eq!(
349 getmap(&node.children[0].children[1], &map),
350 ((1, 5), (1, 11)),
351 );
352
353 assert_eq!(
354 getmap(&node.children[0].children[1].children[0], &map),
355 ((1, 7), (1, 9)),
356 );
357 });
358}
359
360#[test]
361fn imglink() {
362 run("foo [bar](baz) quux", |node, map| {
363 assert_eq!(
364 getmap(&node.children[0].children[1], &map),
365 ((1, 5), (1, 14)),
366 );
367 });
368
369 run("foo ![bar](baz) quux", |node, map| {
370 assert_eq!(
371 getmap(&node.children[0].children[1], &map),
372 ((1, 5), (1, 15)),
373 );
374 });
375}
376