OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Unit tests for markdown. | 5 /// Unit tests for markdown. |
6 library markdownTests; | 6 library markdown.test.markdown_test; |
7 | 7 |
8 import 'package:unittest/unittest.dart'; | 8 import 'package:unittest/unittest.dart'; |
| 9 |
9 import 'package:markdown/markdown.dart'; | 10 import 'package:markdown/markdown.dart'; |
10 | 11 |
| 12 import 'utils.dart'; |
| 13 |
11 /// Most of these tests are based on observing how showdown behaves: | 14 /// Most of these tests are based on observing how showdown behaves: |
12 /// http://softwaremaniacs.org/playground/showdown-highlight/ | 15 /// http://softwaremaniacs.org/playground/showdown-highlight/ |
13 void main() { | 16 void main() { |
14 group('Paragraphs', () { | 17 group('Paragraphs', () { |
15 validate('consecutive lines form a single paragraph', ''' | 18 validate('consecutive lines form a single paragraph', ''' |
16 This is the first line. | 19 This is the first line. |
17 This is the second line. | 20 This is the second line. |
18 ''', ''' | 21 ''', ''' |
19 <p>This is the first line. | 22 <p>This is the first line. |
20 This is the second line.</p> | 23 This is the second line.</p> |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 ''', ''' | 945 ''', ''' |
943 <p> | 946 <p> |
944 <a href="http://foo.com/foo.png" title="optional title"> | 947 <a href="http://foo.com/foo.png" title="optional title"> |
945 <img src="http://foo.com/foo.png" title="optional title"></img> | 948 <img src="http://foo.com/foo.png" title="optional title"></img> |
946 </a> | 949 </a> |
947 </p> | 950 </p> |
948 '''); | 951 '''); |
949 }); | 952 }); |
950 | 953 |
951 group('Resolver', () { | 954 group('Resolver', () { |
952 var nyanResolver = (text) => new Text('~=[,,_${text}_,,]:3'); | 955 nyanResolver(text) => new Text('~=[,,_${text}_,,]:3'); |
| 956 |
953 validate('simple link resolver', ''' | 957 validate('simple link resolver', ''' |
954 resolve [this] thing | 958 resolve [this] thing |
955 ''', ''' | 959 ''', ''' |
956 <p>resolve ~=[,,_this_,,]:3 thing</p> | 960 <p>resolve ~=[,,_this_,,]:3 thing</p> |
957 ''', linkResolver: nyanResolver); | 961 ''', linkResolver: nyanResolver); |
958 validate('simple image resolver', ''' | 962 validate('simple image resolver', ''' |
959 resolve ![this] thing | 963 resolve ![this] thing |
960 ''', ''' | 964 ''', ''' |
961 <p>resolve ~=[,,_this_,,]:3 thing</p> | 965 <p>resolve ~=[,,_this_,,]:3 thing</p> |
962 ''', imageLinkResolver: nyanResolver); | 966 ''', imageLinkResolver: nyanResolver); |
| 967 |
| 968 validate('can resolve link containing inline tags', ''' |
| 969 resolve [*star* _underline_] thing |
| 970 ''', ''' |
| 971 <p>resolve ~=[,,_*star* _underline__,,]:3 thing</p> |
| 972 ''', linkResolver: nyanResolver); |
963 }); | 973 }); |
964 | 974 |
965 group('Custom inline syntax', () { | 975 group('Custom inline syntax', () { |
966 List<InlineSyntax> nyanSyntax = [ | 976 var nyanSyntax = [new TextSyntax('nyan', sub: '~=[,,_,,]:3')]; |
967 new TextSyntax('nyan', sub: '~=[,,_,,]:3') | 977 |
968 ]; | |
969 validate('simple inline syntax', ''' | 978 validate('simple inline syntax', ''' |
970 nyan | 979 nyan |
971 ''', ''' | 980 ''', ''' |
972 <p>~=[,,_,,]:3</p> | 981 <p>~=[,,_,,]:3</p> |
973 ''', inlineSyntaxes: nyanSyntax); | 982 ''', inlineSyntaxes: nyanSyntax); |
974 | 983 |
975 validate('dart custom links', 'links [are<foo>] awesome', | 984 validate('dart custom links', 'links [are<foo>] awesome', |
976 '<p>links <a>are<foo></a> awesome</p>', | 985 '<p>links <a>are<foo></a> awesome</p>', |
977 linkResolver: (text) => new Element.text( | 986 linkResolver: (text) => new Element.text( |
978 'a', text.replaceAll('<', '<'))); | 987 'a', text.replaceAll('<', '<'))); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 This paragraph | 1024 This paragraph |
1016 continues after a newline. | 1025 continues after a newline. |
1017 ''', inlineOnly: true); | 1026 ''', inlineOnly: true); |
1018 validate('ignores block-level markdown syntax', ''' | 1027 validate('ignores block-level markdown syntax', ''' |
1019 1. This will not be an <ol>. | 1028 1. This will not be an <ol>. |
1020 ''', ''' | 1029 ''', ''' |
1021 1. This will not be an <ol>. | 1030 1. This will not be an <ol>. |
1022 ''', inlineOnly: true); | 1031 ''', inlineOnly: true); |
1023 }); | 1032 }); |
1024 } | 1033 } |
1025 | |
1026 /** | |
1027 * Removes eight spaces of leading indentation from a multiline string. | |
1028 * | |
1029 * Note that this is very sensitive to how the literals are styled. They should | |
1030 * be: | |
1031 * ''' | |
1032 * Text starts on own line. Lines up with subsequent lines. | |
1033 * Lines are indented exactly 8 characters from the left margin.''' | |
1034 * | |
1035 * This does nothing if text is only a single line. | |
1036 */ | |
1037 // TODO(nweiz): Make this auto-detect the indentation level from the first | |
1038 // non-whitespace line. | |
1039 String cleanUpLiteral(String text) { | |
1040 var lines = text.split('\n'); | |
1041 if (lines.length <= 1) return text; | |
1042 | |
1043 for (var j = 0; j < lines.length; j++) { | |
1044 if (lines[j].length > 8) { | |
1045 lines[j] = lines[j].substring(8, lines[j].length); | |
1046 } else { | |
1047 lines[j] = ''; | |
1048 } | |
1049 } | |
1050 | |
1051 return lines.join('\n'); | |
1052 } | |
1053 | |
1054 void validate(String description, String markdown, String html, | |
1055 {List<InlineSyntax> inlineSyntaxes, | |
1056 Resolver linkResolver, Resolver imageLinkResolver, | |
1057 bool inlineOnly: false}) { | |
1058 test(description, () { | |
1059 markdown = cleanUpLiteral(markdown); | |
1060 html = cleanUpLiteral(html); | |
1061 | |
1062 var result = markdownToHtml(markdown, | |
1063 inlineSyntaxes: inlineSyntaxes, | |
1064 linkResolver: linkResolver, | |
1065 imageLinkResolver: imageLinkResolver, | |
1066 inlineOnly: inlineOnly); | |
1067 var passed = compareOutput(html, result); | |
1068 | |
1069 if (!passed) { | |
1070 // Remove trailing newline. | |
1071 html = html.substring(0, html.length - 1); | |
1072 | |
1073 var sb = new StringBuffer(); | |
1074 sb.writeln('Expected: ${html.replaceAll("\n", "\n ")}'); | |
1075 sb.writeln(' Actual: ${result.replaceAll("\n", "\n ")}'); | |
1076 | |
1077 fail(sb.toString()); | |
1078 } | |
1079 }); | |
1080 } | |
1081 | |
1082 /// Does a loose comparison of the two strings of HTML. Ignores differences in | |
1083 /// newlines and indentation. | |
1084 bool compareOutput(String a, String b) { | |
1085 int i = 0; | |
1086 int j = 0; | |
1087 | |
1088 skipIgnored(String s, int i) { | |
1089 // Ignore newlines. | |
1090 while ((i < s.length) && (s[i] == '\n')) { | |
1091 i++; | |
1092 // Ignore indentation. | |
1093 while ((i < s.length) && (s[i] == ' ')) i++; | |
1094 } | |
1095 | |
1096 return i; | |
1097 } | |
1098 | |
1099 while (true) { | |
1100 i = skipIgnored(a, i); | |
1101 j = skipIgnored(b, j); | |
1102 | |
1103 // If one string runs out of non-ignored strings, the other must too. | |
1104 if (i == a.length) return j == b.length; | |
1105 if (j == b.length) return i == a.length; | |
1106 | |
1107 if (a[i] != b[j]) return false; | |
1108 i++; | |
1109 j++; | |
1110 } | |
1111 } | |
OLD | NEW |