| 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 |