OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /// Unit tests for markdown. | |
6 library markdownTests; | |
7 | |
8 import 'package:unittest/unittest.dart'; | |
9 | |
10 // TODO(rnystrom): Use "package:" URL (#4968). | |
11 import '../lib/markdown.dart'; | |
12 | |
13 /// Most of these tests are based on observing how showdown behaves: | |
14 /// http://softwaremaniacs.org/playground/showdown-highlight/ | |
15 void main() { | |
16 group('Paragraphs', () { | |
17 validate('consecutive lines form a single paragraph', ''' | |
18 This is the first line. | |
19 This is the second line. | |
20 ''', ''' | |
21 <p>This is the first line. | |
22 This is the second line.</p> | |
23 '''); | |
24 | |
25 // TODO(rnystrom): The rules here for what happens to lines following a | |
26 // paragraph appear to be completely arbitrary in markdown. If it makes the | |
27 // code significantly cleaner, we should consider ourselves free to change | |
28 // these tests. | |
29 | |
30 validate('are terminated by a header', ''' | |
31 para | |
32 # header | |
33 ''', ''' | |
34 <p>para</p> | |
35 <h1>header</h1> | |
36 '''); | |
37 | |
38 validate('are terminated by a setext header', ''' | |
39 para | |
40 header | |
41 == | |
42 ''', ''' | |
43 <p>para</p> | |
44 <h1>header</h1> | |
45 '''); | |
46 | |
47 validate('are terminated by a hr', ''' | |
48 para | |
49 ___ | |
50 ''', ''' | |
51 <p>para</p> | |
52 <hr /> | |
53 '''); | |
54 | |
55 validate('consume an unordered list', ''' | |
56 para | |
57 * list | |
58 ''', ''' | |
59 <p>para | |
60 * list</p> | |
61 '''); | |
62 | |
63 validate('consume an ordered list', ''' | |
64 para | |
65 1. list | |
66 ''', ''' | |
67 <p>para | |
68 1. list</p> | |
69 '''); | |
70 | |
71 // Windows line endings have a \r\n format | |
72 // instead of the unix \n format. | |
73 validate('take account of windows line endings', ''' | |
74 line1\r\n\r\n line2\r\n | |
75 ''', ''' | |
76 <p>line1</p> | |
77 <p>line2</p> | |
78 '''); | |
79 }); | |
80 | |
81 group('Setext headers', () { | |
82 validate('h1', ''' | |
83 text | |
84 === | |
85 ''', ''' | |
86 <h1>text</h1> | |
87 '''); | |
88 | |
89 validate('h2', ''' | |
90 text | |
91 --- | |
92 ''', ''' | |
93 <h2>text</h2> | |
94 '''); | |
95 | |
96 validate('h1 on first line becomes text', ''' | |
97 === | |
98 ''', ''' | |
99 <p>===</p> | |
100 '''); | |
101 | |
102 validate('h2 on first line becomes text', ''' | |
103 - | |
104 ''', ''' | |
105 <p>-</p> | |
106 '''); | |
107 | |
108 validate('h1 turns preceding list into text', ''' | |
109 - list | |
110 === | |
111 ''', ''' | |
112 <h1>- list</h1> | |
113 '''); | |
114 | |
115 validate('h2 turns preceding list into text', ''' | |
116 - list | |
117 === | |
118 ''', ''' | |
119 <h1>- list</h1> | |
120 '''); | |
121 | |
122 validate('h1 turns preceding blockquote into text', ''' | |
123 > quote | |
124 === | |
125 ''', ''' | |
126 <h1>> quote</h1> | |
127 '''); | |
128 | |
129 validate('h2 turns preceding blockquote into text', ''' | |
130 > quote | |
131 === | |
132 ''', ''' | |
133 <h1>> quote</h1> | |
134 '''); | |
135 }); | |
136 | |
137 group('Headers', () { | |
138 validate('h1', ''' | |
139 # header | |
140 ''', ''' | |
141 <h1>header</h1> | |
142 '''); | |
143 | |
144 validate('h2', ''' | |
145 ## header | |
146 ''', ''' | |
147 <h2>header</h2> | |
148 '''); | |
149 | |
150 validate('h3', ''' | |
151 ### header | |
152 ''', ''' | |
153 <h3>header</h3> | |
154 '''); | |
155 | |
156 validate('h4', ''' | |
157 #### header | |
158 ''', ''' | |
159 <h4>header</h4> | |
160 '''); | |
161 | |
162 validate('h5', ''' | |
163 ##### header | |
164 ''', ''' | |
165 <h5>header</h5> | |
166 '''); | |
167 | |
168 validate('h6', ''' | |
169 ###### header | |
170 ''', ''' | |
171 <h6>header</h6> | |
172 '''); | |
173 | |
174 validate('trailing "#" are removed', ''' | |
175 # header ###### | |
176 ''', ''' | |
177 <h1>header</h1> | |
178 '''); | |
179 | |
180 }); | |
181 | |
182 group('Unordered lists', () { | |
183 validate('asterisk, plus and hyphen', ''' | |
184 * star | |
185 - dash | |
186 + plus | |
187 ''', ''' | |
188 <ul> | |
189 <li>star</li> | |
190 <li>dash</li> | |
191 <li>plus</li> | |
192 </ul> | |
193 '''); | |
194 | |
195 validate('allow numbered lines after first', ''' | |
196 * a | |
197 1. b | |
198 ''', ''' | |
199 <ul> | |
200 <li>a</li> | |
201 <li>b</li> | |
202 </ul> | |
203 '''); | |
204 | |
205 validate('allow a tab after the marker', ''' | |
206 *\ta | |
207 +\tb | |
208 -\tc | |
209 1.\td | |
210 ''', ''' | |
211 <ul> | |
212 <li>a</li> | |
213 <li>b</li> | |
214 <li>c</li> | |
215 <li>d</li> | |
216 </ul> | |
217 '''); | |
218 | |
219 validate('wrap items in paragraphs if blank lines separate', ''' | |
220 * one | |
221 | |
222 * two | |
223 ''', ''' | |
224 <ul> | |
225 <li><p>one</p></li> | |
226 <li><p>two</p></li> | |
227 </ul> | |
228 '''); | |
229 | |
230 validate('force paragraph on item before and after blank lines', ''' | |
231 * one | |
232 * two | |
233 | |
234 * three | |
235 ''', ''' | |
236 <ul> | |
237 <li>one</li> | |
238 <li> | |
239 <p>two</p> | |
240 </li> | |
241 <li> | |
242 <p>three</p> | |
243 </li> | |
244 </ul> | |
245 '''); | |
246 | |
247 validate('do not force paragraph if item is already block', ''' | |
248 * > quote | |
249 | |
250 * # header | |
251 ''', ''' | |
252 <ul> | |
253 <li><blockquote><p>quote</p></blockquote></li> | |
254 <li><h1>header</h1></li> | |
255 </ul> | |
256 '''); | |
257 | |
258 validate('can contain multiple paragraphs', ''' | |
259 * one | |
260 | |
261 two | |
262 | |
263 * three | |
264 ''', ''' | |
265 <ul> | |
266 <li> | |
267 <p>one</p> | |
268 <p>two</p> | |
269 </li> | |
270 <li> | |
271 <p>three</p> | |
272 </li> | |
273 </ul> | |
274 '''); | |
275 | |
276 validate('can span newlines', ''' | |
277 * one | |
278 two | |
279 * three | |
280 ''', ''' | |
281 <ul> | |
282 <li> | |
283 <p>one | |
284 two</p> | |
285 </li> | |
286 <li> | |
287 three | |
288 </li> | |
289 </ul> | |
290 '''); | |
291 | |
292 // TODO(rnystrom): This is how most other markdown parsers handle | |
293 // this but that seems like a nasty special case. For now, let's not | |
294 // worry about it. | |
295 /* | |
296 validate('can nest using indentation', ''' | |
297 * parent | |
298 * child | |
299 ''', ''' | |
300 <ul> | |
301 <li>parent | |
302 <ul><li>child</li></ul></li> | |
303 </ul> | |
304 '''); | |
305 */ | |
306 }); | |
307 | |
308 group('Ordered lists', () { | |
309 validate('start with numbers', ''' | |
310 1. one | |
311 45. two | |
312 12345. three | |
313 ''', ''' | |
314 <ol> | |
315 <li>one</li> | |
316 <li>two</li> | |
317 <li>three</li> | |
318 </ol> | |
319 '''); | |
320 | |
321 validate('allow unordered lines after first', ''' | |
322 1. a | |
323 * b | |
324 ''', ''' | |
325 <ol> | |
326 <li>a</li> | |
327 <li>b</li> | |
328 </ol> | |
329 '''); | |
330 }); | |
331 | |
332 group('Blockquotes', () { | |
333 validate('single line', ''' | |
334 > blah | |
335 ''', ''' | |
336 <blockquote> | |
337 <p>blah</p> | |
338 </blockquote> | |
339 '''); | |
340 | |
341 validate('with two paragraphs', ''' | |
342 > first | |
343 > | |
344 > second | |
345 ''', ''' | |
346 <blockquote> | |
347 <p>first</p> | |
348 <p>second</p> | |
349 </blockquote> | |
350 '''); | |
351 | |
352 validate('nested', ''' | |
353 > one | |
354 >> two | |
355 > > > three | |
356 ''', ''' | |
357 <blockquote> | |
358 <p>one</p> | |
359 <blockquote> | |
360 <p>two</p> | |
361 <blockquote> | |
362 <p>three</p> | |
363 </blockquote> | |
364 </blockquote> | |
365 </blockquote> | |
366 '''); | |
367 }); | |
368 | |
369 group('Code blocks', () { | |
370 validate('single line', ''' | |
371 code | |
372 ''', ''' | |
373 <pre><code>code</code></pre> | |
374 '''); | |
375 | |
376 validate('include leading whitespace after indentation', ''' | |
377 zero | |
378 one | |
379 two | |
380 three | |
381 ''', ''' | |
382 <pre><code>zero | |
383 one | |
384 two | |
385 three</code></pre> | |
386 '''); | |
387 | |
388 validate('code blocks separated by newlines form one block', ''' | |
389 zero | |
390 one | |
391 | |
392 two | |
393 | |
394 three | |
395 ''', ''' | |
396 <pre><code>zero | |
397 one | |
398 | |
399 two | |
400 | |
401 three</code></pre> | |
402 '''); | |
403 | |
404 validate('code blocks separated by two newlines form multiple blocks', ''' | |
405 zero | |
406 one | |
407 | |
408 | |
409 two | |
410 | |
411 | |
412 three | |
413 ''', ''' | |
414 <pre><code>zero | |
415 one</code></pre> | |
416 <pre><code>two</code></pre> | |
417 <pre><code>three</code></pre> | |
418 '''); | |
419 | |
420 validate('escape HTML characters', ''' | |
421 <&> | |
422 ''', ''' | |
423 <pre><code><&></code></pre> | |
424 '''); | |
425 }); | |
426 | |
427 group('Fenced code blocks', () { | |
428 validate('without an optional language identifier', ''' | |
429 ``` | |
430 code | |
431 ``` | |
432 ''', ''' | |
433 <pre><code>code | |
434 </code></pre> | |
435 '''); | |
436 | |
437 validate('with an optional language identifier', ''' | |
438 ```dart | |
439 code | |
440 ``` | |
441 ''', ''' | |
442 <pre><code>code | |
443 </code></pre> | |
444 '''); | |
445 | |
446 validate('escape HTML characters', ''' | |
447 ``` | |
448 <&> | |
449 ``` | |
450 ''', ''' | |
451 <pre><code><&> | |
452 </code></pre> | |
453 '''); | |
454 }); | |
455 | |
456 group('Horizontal rules', () { | |
457 validate('from dashes', ''' | |
458 --- | |
459 ''', ''' | |
460 <hr /> | |
461 '''); | |
462 | |
463 validate('from asterisks', ''' | |
464 *** | |
465 ''', ''' | |
466 <hr /> | |
467 '''); | |
468 | |
469 validate('from underscores', ''' | |
470 ___ | |
471 ''', ''' | |
472 <hr /> | |
473 '''); | |
474 | |
475 validate('can include up to two spaces', ''' | |
476 _ _ _ | |
477 ''', ''' | |
478 <hr /> | |
479 '''); | |
480 }); | |
481 | |
482 group('Block-level HTML', () { | |
483 validate('single line', ''' | |
484 <table></table> | |
485 ''', ''' | |
486 <table></table> | |
487 '''); | |
488 | |
489 validate('multi-line', ''' | |
490 <table> | |
491 blah | |
492 </table> | |
493 ''', ''' | |
494 <table> | |
495 blah | |
496 </table> | |
497 '''); | |
498 | |
499 validate('blank line ends block', ''' | |
500 <table> | |
501 blah | |
502 </table> | |
503 | |
504 para | |
505 ''', ''' | |
506 <table> | |
507 blah | |
508 </table> | |
509 <p>para</p> | |
510 '''); | |
511 | |
512 validate('HTML can be bogus', ''' | |
513 <bogus> | |
514 blah | |
515 </weird> | |
516 | |
517 para | |
518 ''', ''' | |
519 <bogus> | |
520 blah | |
521 </weird> | |
522 <p>para</p> | |
523 '''); | |
524 }); | |
525 | |
526 group('Strong', () { | |
527 validate('using asterisks', ''' | |
528 before **strong** after | |
529 ''', ''' | |
530 <p>before <strong>strong</strong> after</p> | |
531 '''); | |
532 | |
533 validate('using underscores', ''' | |
534 before __strong__ after | |
535 ''', ''' | |
536 <p>before <strong>strong</strong> after</p> | |
537 '''); | |
538 | |
539 validate('unmatched asterisks', ''' | |
540 before ** after | |
541 ''', ''' | |
542 <p>before ** after</p> | |
543 '''); | |
544 | |
545 validate('unmatched underscores', ''' | |
546 before __ after | |
547 ''', ''' | |
548 <p>before __ after</p> | |
549 '''); | |
550 | |
551 validate('multiple spans in one text', ''' | |
552 a **one** b __two__ c | |
553 ''', ''' | |
554 <p>a <strong>one</strong> b <strong>two</strong> c</p> | |
555 '''); | |
556 | |
557 validate('multi-line', ''' | |
558 before **first | |
559 second** after | |
560 ''', ''' | |
561 <p>before <strong>first | |
562 second</strong> after</p> | |
563 '''); | |
564 }); | |
565 | |
566 group('Emphasis and strong', () { | |
567 validate('single asterisks', ''' | |
568 before *em* after | |
569 ''', ''' | |
570 <p>before <em>em</em> after</p> | |
571 '''); | |
572 | |
573 validate('single underscores', ''' | |
574 before _em_ after | |
575 ''', ''' | |
576 <p>before <em>em</em> after</p> | |
577 '''); | |
578 | |
579 validate('double asterisks', ''' | |
580 before **strong** after | |
581 ''', ''' | |
582 <p>before <strong>strong</strong> after</p> | |
583 '''); | |
584 | |
585 validate('double underscores', ''' | |
586 before __strong__ after | |
587 ''', ''' | |
588 <p>before <strong>strong</strong> after</p> | |
589 '''); | |
590 | |
591 validate('unmatched asterisk', ''' | |
592 before *after | |
593 ''', ''' | |
594 <p>before *after</p> | |
595 '''); | |
596 | |
597 validate('unmatched underscore', ''' | |
598 before _after | |
599 ''', ''' | |
600 <p>before _after</p> | |
601 '''); | |
602 | |
603 validate('multiple spans in one text', ''' | |
604 a *one* b _two_ c | |
605 ''', ''' | |
606 <p>a <em>one</em> b <em>two</em> c</p> | |
607 '''); | |
608 | |
609 validate('multi-line', ''' | |
610 before *first | |
611 second* after | |
612 ''', ''' | |
613 <p>before <em>first | |
614 second</em> after</p> | |
615 '''); | |
616 | |
617 validate('not processed when surrounded by spaces', ''' | |
618 a * b * c _ d _ e | |
619 ''', ''' | |
620 <p>a * b * c _ d _ e</p> | |
621 '''); | |
622 | |
623 validate('strong then emphasis', ''' | |
624 **strong***em* | |
625 ''', ''' | |
626 <p><strong>strong</strong><em>em</em></p> | |
627 '''); | |
628 | |
629 validate('emphasis then strong', ''' | |
630 *em***strong** | |
631 ''', ''' | |
632 <p><em>em</em><strong>strong</strong></p> | |
633 '''); | |
634 | |
635 validate('emphasis inside strong', ''' | |
636 **strong *em*** | |
637 ''', ''' | |
638 <p><strong>strong <em>em</em></strong></p> | |
639 '''); | |
640 | |
641 validate('mismatched in nested', ''' | |
642 *a _b* c_ | |
643 ''', ''' | |
644 <p><em>a _b</em> c_</p> | |
645 '''); | |
646 | |
647 validate('cannot nest tags of same type', ''' | |
648 *a _b *c* d_ e* | |
649 ''', ''' | |
650 <p><em>a _b </em>c<em> d_ e</em></p> | |
651 '''); | |
652 }); | |
653 | |
654 group('Inline code', () { | |
655 validate('simple case', ''' | |
656 before `source` after | |
657 ''', ''' | |
658 <p>before <code>source</code> after</p> | |
659 '''); | |
660 | |
661 validate('unmatched backtick', ''' | |
662 before ` after | |
663 ''', ''' | |
664 <p>before ` after</p> | |
665 '''); | |
666 validate('multiple spans in one text', ''' | |
667 a `one` b `two` c | |
668 ''', ''' | |
669 <p>a <code>one</code> b <code>two</code> c</p> | |
670 '''); | |
671 | |
672 validate('multi-line', ''' | |
673 before `first | |
674 second` after | |
675 ''', ''' | |
676 <p>before <code>first | |
677 second</code> after</p> | |
678 '''); | |
679 | |
680 validate('simple double backticks', ''' | |
681 before ``source`` after | |
682 ''', ''' | |
683 <p>before <code>source</code> after</p> | |
684 '''); | |
685 | |
686 validate('double backticks', ''' | |
687 before ``can `contain` backticks`` after | |
688 ''', ''' | |
689 <p>before <code>can `contain` backticks</code> after</p> | |
690 '''); | |
691 | |
692 validate('double backticks with spaces', ''' | |
693 before `` `tick` `` after | |
694 ''', ''' | |
695 <p>before <code>`tick`</code> after</p> | |
696 '''); | |
697 | |
698 validate('multiline double backticks with spaces', ''' | |
699 before ``in `tick` | |
700 another`` after | |
701 ''', ''' | |
702 <p>before <code>in `tick` | |
703 another</code> after</p> | |
704 '''); | |
705 | |
706 validate('ignore markup inside code', ''' | |
707 before `*b* _c_` after | |
708 ''', ''' | |
709 <p>before <code>*b* _c_</code> after</p> | |
710 '''); | |
711 | |
712 validate('escape HTML characters', ''' | |
713 `<&>` | |
714 ''', ''' | |
715 <p><code><&></code></p> | |
716 '''); | |
717 | |
718 validate('escape HTML tags', ''' | |
719 '*' `<em>` | |
720 ''', ''' | |
721 <p>'*' <code><em></code></p> | |
722 '''); | |
723 }); | |
724 | |
725 group('HTML encoding', () { | |
726 validate('less than and ampersand are escaped', ''' | |
727 < & | |
728 ''', ''' | |
729 <p>< &</p> | |
730 '''); | |
731 validate('greater than is not escaped', ''' | |
732 not you > | |
733 ''', ''' | |
734 <p>not you ></p> | |
735 '''); | |
736 validate('existing entities are untouched', ''' | |
737 & | |
738 ''', ''' | |
739 <p>&</p> | |
740 '''); | |
741 }); | |
742 | |
743 group('Autolinks', () { | |
744 validate('basic link', ''' | |
745 before <http://foo.com/> after | |
746 ''', ''' | |
747 <p>before <a href="http://foo.com/">http://foo.com/</a> after</p> | |
748 '''); | |
749 validate('handles ampersand in url', ''' | |
750 <http://foo.com/?a=1&b=2> | |
751 ''', ''' | |
752 <p><a href="http://foo.com/?a=1&b=2">http://foo.com/?a=1&b=2</a></p> | |
753 '''); | |
754 }); | |
755 | |
756 group('Reference links', () { | |
757 validate('double quotes for title', ''' | |
758 links [are] [a] awesome | |
759 | |
760 [a]: http://foo.com "woo" | |
761 ''', ''' | |
762 <p>links <a href="http://foo.com" title="woo">are</a> awesome</p> | |
763 '''); | |
764 validate('single quoted title', """ | |
765 links [are] [a] awesome | |
766 | |
767 [a]: http://foo.com 'woo' | |
768 """, ''' | |
769 <p>links <a href="http://foo.com" title="woo">are</a> awesome</p> | |
770 '''); | |
771 validate('parentheses for title', ''' | |
772 links [are] [a] awesome | |
773 | |
774 [a]: http://foo.com (woo) | |
775 ''', ''' | |
776 <p>links <a href="http://foo.com" title="woo">are</a> awesome</p> | |
777 '''); | |
778 validate('no title', ''' | |
779 links [are] [a] awesome | |
780 | |
781 [a]: http://foo.com | |
782 ''', ''' | |
783 <p>links <a href="http://foo.com">are</a> awesome</p> | |
784 '''); | |
785 validate('unknown link becomes plaintext', ''' | |
786 [not] [known] | |
787 ''', ''' | |
788 <p>[not] [known]</p> | |
789 '''); | |
790 validate('can style link contents', ''' | |
791 links [*are*] [a] awesome | |
792 | |
793 [a]: http://foo.com | |
794 ''', ''' | |
795 <p>links <a href="http://foo.com"><em>are</em></a> awesome</p> | |
796 '''); | |
797 validate('inline styles after a bad link are processed', ''' | |
798 [bad] `code` | |
799 ''', ''' | |
800 <p>[bad] <code>code</code></p> | |
801 '''); | |
802 validate('empty reference uses text from link', ''' | |
803 links [are][] awesome | |
804 | |
805 [are]: http://foo.com | |
806 ''', ''' | |
807 <p>links <a href="http://foo.com">are</a> awesome</p> | |
808 '''); | |
809 validate('references are case-insensitive', ''' | |
810 links [ARE][] awesome | |
811 | |
812 [are]: http://foo.com | |
813 ''', ''' | |
814 <p>links <a href="http://foo.com">ARE</a> awesome</p> | |
815 '''); | |
816 }); | |
817 | |
818 group('Inline links', () { | |
819 validate('double quotes for title', ''' | |
820 links [are](http://foo.com "woo") awesome | |
821 ''', ''' | |
822 <p>links <a href="http://foo.com" title="woo">are</a> awesome</p> | |
823 '''); | |
824 validate('no title', ''' | |
825 links [are] (http://foo.com) awesome | |
826 ''', ''' | |
827 <p>links <a href="http://foo.com">are</a> awesome</p> | |
828 '''); | |
829 validate('can style link contents', ''' | |
830 links [*are*](http://foo.com) awesome | |
831 ''', ''' | |
832 <p>links <a href="http://foo.com"><em>are</em></a> awesome</p> | |
833 '''); | |
834 }); | |
835 | |
836 group('Resolver', () { | |
837 var nyanResolver = (text) => new Text('~=[,,_${text}_,,]:3'); | |
838 validate('simple resolver', ''' | |
839 resolve [this] thing | |
840 ''', ''' | |
841 <p>resolve ~=[,,_this_,,]:3 thing</p> | |
842 ''', linkResolver: nyanResolver); | |
843 }); | |
844 | |
845 group('Custom inline syntax', () { | |
846 List<InlineSyntax> nyanSyntax = | |
847 [new TextSyntax('nyan', sub: '~=[,,_,,]:3')]; | |
848 validate('simple inline syntax', ''' | |
849 nyan | |
850 ''', ''' | |
851 <p>~=[,,_,,]:3</p> | |
852 ''', inlineSyntaxes: nyanSyntax); | |
853 | |
854 // TODO(amouravski): need more tests here for custom syntaxes, as some | |
855 // things are not quite working properly. The regexps are sometime a little | |
856 // too greedy, I think. | |
857 }); | |
858 } | |
859 | |
860 /** | |
861 * Removes eight spaces of leading indentation from a multiline string. | |
862 * | |
863 * Note that this is very sensitive to how the literals are styled. They should | |
864 * be: | |
865 * ''' | |
866 * Text starts on own line. Lines up with subsequent lines. | |
867 * Lines are indented exactly 8 characters from the left margin.''' | |
868 * | |
869 * This does nothing if text is only a single line. | |
870 */ | |
871 // TODO(nweiz): Make this auto-detect the indentation level from the first | |
872 // non-whitespace line. | |
873 String cleanUpLiteral(String text) { | |
874 var lines = text.split('\n'); | |
875 if (lines.length <= 1) return text; | |
876 | |
877 for (var j = 0; j < lines.length; j++) { | |
878 if (lines[j].length > 8) { | |
879 lines[j] = lines[j].substring(8, lines[j].length); | |
880 } else { | |
881 lines[j] = ''; | |
882 } | |
883 } | |
884 | |
885 return lines.join('\n'); | |
886 } | |
887 | |
888 validate(String description, String markdown, String html, | |
889 {bool verbose: false, inlineSyntaxes, linkResolver}) { | |
890 test(description, () { | |
891 markdown = cleanUpLiteral(markdown); | |
892 html = cleanUpLiteral(html); | |
893 | |
894 var result = markdownToHtml(markdown, inlineSyntaxes: inlineSyntaxes, | |
895 linkResolver: linkResolver); | |
896 var passed = compareOutput(html, result); | |
897 | |
898 if (!passed) { | |
899 // Remove trailing newline. | |
900 html = html.substring(0, html.length - 1); | |
901 | |
902 print('FAIL: $description'); | |
903 print(' expect: ${html.replaceAll("\n", "\n ")}'); | |
904 print(' actual: ${result.replaceAll("\n", "\n ")}'); | |
905 print(''); | |
906 } | |
907 | |
908 expect(passed, isTrue, verbose: verbose); | |
909 }); | |
910 } | |
911 | |
912 /// Does a loose comparison of the two strings of HTML. Ignores differences in | |
913 /// newlines and indentation. | |
914 compareOutput(String a, String b) { | |
915 int i = 0; | |
916 int j = 0; | |
917 | |
918 skipIgnored(String s, int i) { | |
919 // Ignore newlines. | |
920 while ((i < s.length) && (s[i] == '\n')) { | |
921 i++; | |
922 // Ignore indentation. | |
923 while ((i < s.length) && (s[i] == ' ')) i++; | |
924 } | |
925 | |
926 return i; | |
927 } | |
928 | |
929 while (true) { | |
930 i = skipIgnored(a, i); | |
931 j = skipIgnored(b, j); | |
932 | |
933 // If one string runs out of non-ignored strings, the other must too. | |
934 if (i == a.length) return j == b.length; | |
935 if (j == b.length) return i == a.length; | |
936 | |
937 if (a[i] != b[j]) return false; | |
938 i++; | |
939 j++; | |
940 } | |
941 } | |
OLD | NEW |