1 | var Markdown = require('Markdown').Markdown,
|
2 | mk_block = Markdown.mk_block;
|
3 |
|
4 | var tests = {
|
5 | meta: function(fn) {
|
6 | return function() { fn( new Markdown ) }
|
7 | }
|
8 | };
|
9 |
|
10 | tests = {
|
11 | test_split_block: tests.meta(function(md) {
|
12 | asserts.same(
|
13 | md.split_blocks( "# h1 #\n\npara1\npara1L2\n \n\n\n\npara2\n" ),
|
14 | [mk_block( "# h1 #", "\n\n", 1 ),
|
15 | mk_block( "para1\npara1L2", "\n \n\n\n\n", 3 ),
|
16 | mk_block( "para2", "\n", 9 )
|
17 | ],
|
18 | "split_block should record trailing newlines");
|
19 |
|
20 | asserts.same(
|
21 | md.split_blocks( "\n\n# heading #\n\npara\n" ),
|
22 | [mk_block( "# heading #", "\n\n", 3 ),
|
23 | mk_block( "para", "\n", 5 )
|
24 | ],
|
25 | "split_block should ignore leading newlines");
|
26 | }),
|
27 |
|
28 | test_headers: tests.meta(function(md) {
|
29 | var h1 = md.dialect.block.atxHeader( "# h1 #\n\n", [] ),
|
30 | h2;
|
31 |
|
32 | asserts.same(
|
33 | h1,
|
34 | md.dialect.block.setextHeader( "h1\n===\n\n", [] ),
|
35 | "Atx and Setext style H1s should produce the same output" );
|
36 |
|
37 | asserts.same(
|
38 | md.dialect.block.atxHeader("# h1\n\n"),
|
39 | h1,
|
40 | "Closing # optional on atxHeader");
|
41 |
|
42 | asserts.same(
|
43 | h2 = md.dialect.block.atxHeader( "## h2\n\n", [] ),
|
44 | [["header", {level: 2}, "h2"]],
|
45 | "Atx h2 has right level");
|
46 |
|
47 | asserts.same(
|
48 | h2,
|
49 | md.dialect.block.setextHeader( "h2\n---\n\n", [] ),
|
50 | "Atx and Setext style H2s should produce the same output" );
|
51 |
|
52 | }),
|
53 |
|
54 | test_code: tests.meta(function(md) {
|
55 | var code = md.dialect.block.code,
|
56 | next = [ mk_block("next") ];
|
57 |
|
58 | asserts.same(
|
59 | code.call( md, mk_block(" foo\n bar"), next ),
|
60 | [["code_block", "foo\nbar" ]],
|
61 | "Code block correct");
|
62 |
|
63 | asserts.same(
|
64 | next, [mk_block("next")],
|
65 | "next untouched when its not code");
|
66 |
|
67 | next = [];
|
68 | asserts.same(
|
69 | code.call( md, mk_block(" foo\n bar"), next ),
|
70 | [["code_block", "foo" ]],
|
71 | "Code block correct for abutting para");
|
72 |
|
73 | asserts.same(
|
74 | next, [mk_block(" bar")],
|
75 | "paragraph put back into next block");
|
76 |
|
77 | asserts.same(
|
78 | code.call( md, mk_block(" foo"), [mk_block(" bar"), ] ),
|
79 | [["code_block", "foo\n\nbar" ]],
|
80 | "adjacent code blocks ");
|
81 |
|
82 | asserts.same(
|
83 | code.call( md, mk_block(" foo","\n \n \n"), [mk_block(" bar"), ] ),
|
84 | [["code_block", "foo\n\n\nbar" ]],
|
85 | "adjacent code blocks preserve correct number of empty lines");
|
86 |
|
87 | }),
|
88 |
|
89 | test_bulletlist: tests.meta(function(md) {
|
90 | var bl = function() { return md.dialect.block.lists.apply(md, arguments) };
|
91 |
|
92 | asserts.same(
|
93 | bl( mk_block("* foo\n* bar"), [] ),
|
94 | [ [ "bulletlist", [ "listitem", "foo" ], [ "listitem", "bar" ] ] ],
|
95 | "single line bullets");
|
96 |
|
97 | asserts.same(
|
98 | bl( mk_block("* [text](url)" ), [] ),
|
99 | [ [ "bulletlist", [ "listitem", [ "link", { href: "url" }, "text" ] ] ] ],
|
100 | "link in bullet");
|
101 |
|
102 | asserts.same(
|
103 | bl( mk_block("* foo\nbaz\n* bar\nbaz"), [] ),
|
104 | [ [ "bulletlist", [ "listitem", "foo\nbaz" ], [ "listitem", "bar\nbaz" ] ] ],
|
105 | "multiline lazy bullets");
|
106 |
|
107 | asserts.same(
|
108 | bl( mk_block("* foo\n baz\n* bar\n baz"), [] ),
|
109 | [ [ "bulletlist", [ "listitem", "foo\nbaz" ], [ "listitem", "bar\nbaz" ] ] ],
|
110 | "multiline tidy bullets");
|
111 |
|
112 | asserts.same(
|
113 | bl( mk_block("* foo\n baz"), [] ),
|
114 | [ [ "bulletlist", [ "listitem", "foo\n baz" ] ] ],
|
115 | "only trim 4 spaces from the start of the line");
|
116 |
|
117 | |
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | asserts.same(
|
125 | bl( mk_block(" * one"), [ mk_block(" two") ] ),
|
126 | [ [ "bulletlist", [ "listitem", [ "para", "one" ], [ "para", "two" ] ] ] ],
|
127 | "loose bullet lists can have multiple paragraphs");
|
128 |
|
129 | |
130 |
|
131 |
|
132 |
|
133 | asserts.same(
|
134 | bl( mk_block(" *\nfoo") ),
|
135 | undefined,
|
136 | "Space required after bullet to trigger list");
|
137 |
|
138 | |
139 |
|
140 |
|
141 |
|
142 |
|
143 | asserts.same(
|
144 | bl( mk_block(" * \nfoo\nbar"), [ ] ),
|
145 | [ [ "bulletlist", [ "listitem", "foo\nbar" ] ] ],
|
146 | "space+continuation lines");
|
147 |
|
148 |
|
149 | |
150 |
|
151 |
|
152 |
|
153 |
|
154 | asserts.same(
|
155 | bl( mk_block(" * foo\n" +
|
156 | " * bar\n" +
|
157 | " * baz"),
|
158 | [] ),
|
159 | [ [ "bulletlist",
|
160 | [ "listitem",
|
161 | "foo",
|
162 | [ "bulletlist",
|
163 | [ "listitem",
|
164 | "bar",
|
165 | [ "bulletlist",
|
166 | [ "listitem", "baz" ]
|
167 | ]
|
168 | ]
|
169 | ]
|
170 | ]
|
171 | ] ],
|
172 | "Interesting indented lists I");
|
173 |
|
174 | |
175 |
|
176 |
|
177 |
|
178 |
|
179 | asserts.same(
|
180 | bl( mk_block(" * foo\n * bar\n * baz"), [] ),
|
181 | [ [ "bulletlist",
|
182 | [ "listitem",
|
183 | "foo",
|
184 | [ "bulletlist",
|
185 | [ "listitem", "bar" ]
|
186 | ]
|
187 | ],
|
188 | [ "listitem", "baz" ]
|
189 | ] ],
|
190 | "Interesting indented lists II");
|
191 |
|
192 | |
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 | asserts.same(
|
199 | bl( mk_block(" * foo\n * bar\n* baz\n * fnord"), [] ),
|
200 | [ [ "bulletlist",
|
201 | [ "listitem",
|
202 | "foo",
|
203 | [ "bulletlist",
|
204 | [ "listitem", "bar" ],
|
205 | [ "listitem", "baz" ],
|
206 | [ "listitem", "fnord" ]
|
207 | ]
|
208 | ]
|
209 | ] ],
|
210 | "Interesting indented lists III");
|
211 |
|
212 | |
213 |
|
214 |
|
215 |
|
216 |
|
217 | asserts.same(
|
218 | bl( mk_block(" * foo"), [ mk_block(" 1. bar\n") ] ),
|
219 | [ [ "bulletlist",
|
220 | ["listitem", ["para", "foo"] ],
|
221 | ["listitem", ["para", "bar"] ]
|
222 | ] ],
|
223 | "Different lists at same indent IV");
|
224 |
|
225 | |
226 |
|
227 |
|
228 |
|
229 |
|
230 | asserts.same(
|
231 | bl( mk_block(" * foo\n * bar\n * baz"), [] ),
|
232 | [ [ "bulletlist",
|
233 | [ "listitem",
|
234 | "foo",
|
235 | [ "bulletlist",
|
236 | ["listitem", "bar"],
|
237 | ["listitem", "baz"],
|
238 | ]
|
239 | ]
|
240 | ] ],
|
241 | "Indenting Case V")
|
242 |
|
243 | |
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 | asserts.same(
|
250 | bl( mk_block("* one\n * two\n * three\n * four"), [] ),
|
251 | [ [ "bulletlist",
|
252 | [ "listitem",
|
253 | "one",
|
254 | [ "bulletlist",
|
255 | [ "listitem",
|
256 | "two",
|
257 | [ "bulletlist",
|
258 | [ "listitem",
|
259 | "three",
|
260 | [ "bulletlist",
|
261 | [ "listitem", "four" ]
|
262 | ]
|
263 | ]
|
264 | ]
|
265 | ]
|
266 | ]
|
267 | ]
|
268 | ] ],
|
269 | "deep nested lists VI")
|
270 |
|
271 | |
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 | asserts.same(
|
284 | bl( mk_block(" * foo\n" +
|
285 | " * bar\n" +
|
286 | " * baz\n" +
|
287 | "* HATE\n" +
|
288 | " * flibble\n" +
|
289 | " * quxx\n" +
|
290 | " * nest?\n" +
|
291 | " * where\n" +
|
292 | " * am\n" +
|
293 | " * i?"),
|
294 | [] ),
|
295 | [ [ "bulletlist",
|
296 | [ "listitem",
|
297 | "foo",
|
298 | [ "bulletlist",
|
299 | ["listitem", "bar"],
|
300 | ["listitem", "baz"],
|
301 | ["listitem", "HATE"],
|
302 | ["listitem", "flibble"]
|
303 | ]
|
304 | ],
|
305 | [ "listitem",
|
306 | "quxx",
|
307 | [ "bulletlist",
|
308 | [ "listitem",
|
309 | "nest?",
|
310 | [ "bulletlist",
|
311 | ["listitem", "where"],
|
312 | ["listitem", "am"],
|
313 | ["listitem", "i?"]
|
314 | ]
|
315 | ]
|
316 | ]
|
317 | ]
|
318 | ] ],
|
319 | "Indenting Case VII");
|
320 |
|
321 | |
322 |
|
323 |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 | asserts.same(
|
330 | bl( mk_block(" * one\n" +
|
331 | " 1. two\n" +
|
332 | " * three\n" +
|
333 | " * four",
|
334 | "\n\n"),
|
335 | [ mk_block(" foo") ] ),
|
336 | [ [ "bulletlist",
|
337 | [ "listitem",
|
338 | ["para", "one"],
|
339 | [ "numberlist",
|
340 | [ "listitem",
|
341 | ["para", "two"],
|
342 | [ "bulletlist",
|
343 | [ "listitem",
|
344 | [ "para", "three\n * four"],
|
345 | ["code_block", "foo"]
|
346 | ]
|
347 | ]
|
348 | ]
|
349 | ]
|
350 | ]
|
351 | ] ],
|
352 | "Case VIII: Deep nesting and code block");
|
353 |
|
354 | }),
|
355 |
|
356 | test_horizRule: tests.meta(function(md) {
|
357 | var hr = md.dialect.block.horizRule,
|
358 | strs = ["---", "_ __", "** ** **", "--- "];
|
359 | strs.forEach( function(s) {
|
360 | asserts.same(
|
361 | hr.call( md, mk_block(s), [] ),
|
362 | [ [ "hr" ] ],
|
363 | "simple hr from " + uneval(s));
|
364 | });
|
365 | }),
|
366 |
|
367 | test_blockquote: tests.meta(function(md) {
|
368 | var bq = md.dialect.block.blockquote;
|
369 | asserts.same(
|
370 | bq.call( md, mk_block("> foo\n> bar"), [] ),
|
371 | [ ["blockquote", ["para", "foo\nbar"] ] ],
|
372 | "simple blockquote");
|
373 |
|
374 |
|
375 | asserts.same(
|
376 | bq.call( md, mk_block("> foo\n> bar\n>\n>- - - "), [] ),
|
377 | [ ["blockquote",
|
378 | ["para", "foo\nbar"],
|
379 | ["hr"]
|
380 | ] ],
|
381 | "blockquote with interesting content");
|
382 |
|
383 | }),
|
384 |
|
385 | test_referenceDefn: tests.meta(function(md) {
|
386 | var rd = md.dialect.block.referenceDefn;
|
387 |
|
388 | [ '[id]: http://example.com/ "Optional Title Here"',
|
389 | "[id]: http://example.com/ 'Optional Title Here'",
|
390 | '[id]: http://example.com/ (Optional Title Here)'
|
391 | ].forEach( function(s) {
|
392 | md.tree = ["markdown"];
|
393 |
|
394 | asserts.same(rd.call( md, mk_block(s) ), [], "ref processed");
|
395 |
|
396 | asserts.same(md.tree[ 1 ].references,
|
397 | { "id": { href: "http://example.com/", title: "Optional Title Here" } },
|
398 | "reference extracted");
|
399 | });
|
400 |
|
401 |
|
402 | md.tree = ["markdown"];
|
403 | var next = [];
|
404 | asserts.same(rd.call( md, mk_block("[id]: example.com\npara"), next ), [], "ref processed");
|
405 | asserts.same(md.tree[ 1 ].references, { "id": { href: "example.com" } }, "reference extracted");
|
406 | asserts.same(next, [ mk_block("para") ], "paragraph put back into blocks");
|
407 |
|
408 | }),
|
409 |
|
410 | test_inline_br: tests.meta(function(md) {
|
411 | asserts.same(
|
412 | md.processInline("foo \n\\[bar"),
|
413 | [ "foo", ["linebreak"], "[bar" ], "linebreak+escape");
|
414 | }),
|
415 |
|
416 | test_inline_escape: tests.meta(function(md) {
|
417 | asserts.same( md.processInline("\\bar"), [ "\\bar" ], "invalid escape" );
|
418 | asserts.same( md.processInline("\\*foo*"), [ "*foo*" ], "escaped em" );
|
419 | }),
|
420 |
|
421 | test_inline_code: tests.meta(function(md) {
|
422 | asserts.same( md.processInline("`bar`"), [ ["inlinecode", "bar" ] ], "code I" );
|
423 | asserts.same( md.processInline("``b`ar``"), [ ["inlinecode", "b`ar" ] ], "code II" );
|
424 | asserts.same( md.processInline("```bar``` baz"), [ ["inlinecode", "bar" ], " baz" ], "code III" );
|
425 | }),
|
426 |
|
427 | test_inline_strong_em: tests.meta(function(md) {
|
428 |
|
429 | asserts.same( md.processInline("foo *abc* bar"), [ "foo ", ["em", "abc" ], " bar" ], "strong/em I" );
|
430 | asserts.same( md.processInline("*abc `code`"), [ "*abc ", ["inlinecode", "code" ] ], "strong/em II" );
|
431 | asserts.same( md.processInline("*abc**def* after"), [ ["em", "abc**def" ], " after" ], "strong/em III" );
|
432 | asserts.same( md.processInline("*em **strong * wtf**"), [ ["em", "em **strong " ], " wtf**" ], "strong/em IV" );
|
433 | asserts.same( md.processInline("*foo _b*a*r baz"), [ [ "em", "foo _b" ], "a*r baz" ], "strong/em V" );
|
434 | }),
|
435 |
|
436 | test_inline_img: tests.meta(function(md) {
|
437 |
|
438 | asserts.same( md.processInline( "![alt] (url)" ),
|
439 | [ [ "img", { href: "url", alt: "alt" } ] ],
|
440 | "inline img I" );
|
441 |
|
442 | asserts.same( md.processInline( "![alt](url 'title')" ),
|
443 | [ [ "img", { href: "url", alt: "alt", title: "title" } ] ],
|
444 | "inline img II" );
|
445 |
|
446 | asserts.same( md.processInline( "![alt] (url 'tit'le') after')" ),
|
447 | [ [ "img", { href: "url", alt: "alt", title: "tit'le" } ], " after')" ],
|
448 | "inline img III" );
|
449 |
|
450 | asserts.same( md.processInline( "![alt] (url \"title\")" ),
|
451 | [ [ "img", { href: "url", alt: "alt", title: "title" } ] ],
|
452 | "inline img IV" );
|
453 |
|
454 | asserts.same( md.processInline( "![alt][id]" ),
|
455 | [ [ "img_ref", { ref: "id", alt: "alt", text: "![alt][id]" } ] ],
|
456 | "ref img I" );
|
457 |
|
458 | asserts.same( md.processInline( "![alt] [id]" ),
|
459 | [ [ "img_ref", { ref: "id", alt: "alt", text: "![alt] [id]" } ] ],
|
460 | "ref img II" );
|
461 | }),
|
462 |
|
463 | test_inline_link: tests.meta(function(md) {
|
464 |
|
465 | asserts.same( md.processInline( "[text] (url)" ),
|
466 | [ [ "link", { href: "url" }, "text" ] ],
|
467 | "inline link I" );
|
468 |
|
469 | asserts.same( md.processInline( "[text](url 'title')" ),
|
470 | [ [ "link", { href: "url", title: "title" }, "text" ] ],
|
471 | "inline link II" );
|
472 |
|
473 | asserts.same( md.processInline( "[text](url 'tit'le') after')" ),
|
474 | [ [ "link", { href: "url", title: "tit'le" }, "text" ], " after')" ],
|
475 | "inline link III" );
|
476 |
|
477 | asserts.same( md.processInline( "[text](url \"title\")" ),
|
478 | [ [ "link", { href: "url", title: "title" }, "text" ] ],
|
479 | "inline link IV" );
|
480 |
|
481 | asserts.same( md.processInline( "[text][id]" ),
|
482 | [ [ "link_ref", { ref: "id", original: "[text][id]" }, "text" ] ],
|
483 | "ref link I" );
|
484 |
|
485 | asserts.same( md.processInline( "[text] [id]" ),
|
486 | [ [ "link_ref", { ref: "id", original: "[text] [id]" }, "text" ] ],
|
487 | "ref link II" );
|
488 | }),
|
489 |
|
490 | test_inline_autolink: tests.meta(function(md) {
|
491 |
|
492 | asserts.same( md.processInline( "<http://foo.com>" ),
|
493 | [ [ "link", { href: "http://foo.com" }, "http://foo.com" ] ],
|
494 | "autolink I" );
|
495 |
|
496 | asserts.same( md.processInline( "<mailto:foo@bar.com>" ),
|
497 | [ [ "link", { href: "mailto:foo@bar.com" }, "foo@bar.com" ] ],
|
498 | "autolink II" );
|
499 |
|
500 | asserts.same( md.processInline( "<foo@bar.com>" ),
|
501 | [ [ "link", { href: "mailto:foo@bar.com" }, "foo@bar.com" ] ],
|
502 | "autolink III" );
|
503 | }),
|
504 | }
|
505 |
|
506 |
|
507 | if (require.main === module) {
|
508 | var asserts = require('test').asserts;
|
509 | require('test').runner(tests);
|
510 | }
|