浏览代码

Adding PHP BlockTests. Normalizing all assertions to expected,actual ordering. Better normalization of HTML whitespace in tests

main
Rocketsoup 1年前
父节点
当前提交
b26c37f0fb

+ 98
- 98
jstest/BlockTests.js 查看文件

@@ -11,58 +11,58 @@ class BlockTests extends BaseTest {
11 11
 
12 12
 	test_paragraphs() {
13 13
 		let markdown = "Lorem ipsum\n\nDolor sit amet";
14
-		let expected = "<p>Lorem ipsum</p> <p>Dolor sit amet</p>";
14
+		let expected = "<p>Lorem ipsum</p><p>Dolor sit amet</p>";
15 15
 		let actual = this.md(markdown);
16
-		this.assertEqual(actual, expected);
16
+		this.assertEqual(expected, actual);
17 17
 	}
18 18
 
19 19
 	test_paragraph_lineGrouping() {
20 20
 		let markdown = "Lorem ipsum\ndolor sit amet";
21 21
 		let expected = "Lorem ipsum dolor sit amet";
22 22
 		let actual = this.md(markdown);
23
-		this.assertEqual(actual, expected);
23
+		this.assertEqual(expected, actual);
24 24
 	}
25 25
 
26 26
 	test_header_underlineH1() {
27 27
 		let markdown = "Header 1\n===\n\nLorem ipsum";
28
-		let expected = "<h1>Header 1</h1> <p>Lorem ipsum</p>";
28
+		let expected = "<h1>Header 1</h1><p>Lorem ipsum</p>";
29 29
 		let actual = this.md(markdown);
30
-		this.assertEqual(actual, expected);
30
+		this.assertEqual(expected, actual);
31 31
 	}
32 32
 
33 33
 	test_header_underlineH2() {
34 34
 		let markdown = "Header 2\n---\n\nLorem ipsum";
35
-		let expected = "<h2>Header 2</h2> <p>Lorem ipsum</p>";
35
+		let expected = "<h2>Header 2</h2><p>Lorem ipsum</p>";
36 36
 		let actual = this.md(markdown);
37
-		this.assertEqual(actual, expected);
37
+		this.assertEqual(expected, actual);
38 38
 	}
39 39
 
40 40
 	test_header_hash() {
41 41
 		let markdown = "# Header 1\n## Header 2\n### Header 3\n#### Header 4\n##### Header 5\n###### Header 6\n";
42
-		let expected = '<h1>Header 1</h1> <h2>Header 2</h2> <h3>Header 3</h3> <h4>Header 4</h4> <h5>Header 5</h5> <h6>Header 6</h6>';
42
+		let expected = '<h1>Header 1</h1><h2>Header 2</h2><h3>Header 3</h3><h4>Header 4</h4><h5>Header 5</h5><h6>Header 6</h6>';
43 43
 		let actual = this.md(markdown);
44
-		this.assertEqual(actual, expected);
44
+		this.assertEqual(expected, actual);
45 45
 	}
46 46
 
47 47
 	test_header_hash_trailing() {
48 48
 		let markdown = "# Header 1 #\n## Header 2 ##\n### Header 3 ######";
49
-		let expected = '<h1>Header 1</h1> <h2>Header 2</h2> <h3>Header 3</h3>';
49
+		let expected = '<h1>Header 1</h1><h2>Header 2</h2><h3>Header 3</h3>';
50 50
 		let actual = this.md(markdown);
51
-		this.assertEqual(actual, expected);
51
+		this.assertEqual(expected, actual);
52 52
 	}
53 53
 
54 54
 	test_unorderedList() {
55 55
 		let markdown = "* Lorem\n* Ipsum\n* Dolor";
56
-		let expected = '<ul> <li>Lorem</li> <li>Ipsum</li> <li>Dolor</li> </ul>';
56
+		let expected = '<ul><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ul>';
57 57
 		let actual = this.md(markdown);
58
-		this.assertEqual(actual, expected);
58
+		this.assertEqual(expected, actual);
59 59
 	}
60 60
 
61 61
 	test_unorderedList_nested() {
62 62
 		let markdown = "* Lorem\n + Ipsum\n* Dolor";
63
-		let expected = '<ul> <li>Lorem<ul> <li>Ipsum</li> </ul> </li> <li>Dolor</li> </ul>';
63
+		let expected = '<ul><li>Lorem<ul><li>Ipsum</li></ul></li><li>Dolor</li></ul>';
64 64
 		let actual = this.md(markdown);
65
-		this.assertEqual(actual, expected);
65
+		this.assertEqual(expected, actual);
66 66
 	}
67 67
 
68 68
 	test_unorderedList_hitch() {
@@ -70,101 +70,101 @@ class BlockTests extends BaseTest {
70 70
 		// point, not forever but a REALLY long time
71 71
 		this.profile(1.0, () => {
72 72
 			let markdown = "Testing\n\n* ";
73
-			let expected = '<p>Testing</p> <ul> <li></li> </ul>';
73
+			let expected = '<p>Testing</p><ul><li></li></ul>';
74 74
 			let actual = this.md(markdown);
75
-			this.assertEqual(actual, expected);
75
+			this.assertEqual(expected, actual);
76 76
 		});
77 77
 	}
78 78
 
79 79
 	test_orderedList() {
80 80
 		let markdown = "1. Lorem\n1. Ipsum\n5. Dolor";
81
-		let expected = '<ol> <li>Lorem</li> <li>Ipsum</li> <li>Dolor</li> </ol>';
81
+		let expected = '<ol><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ol>';
82 82
 		let actual = this.md(markdown);
83
-		this.assertEqual(actual, expected);
83
+		this.assertEqual(expected, actual);
84 84
 	}
85 85
 
86 86
 	test_orderedList_numbering() {
87 87
 		let markdown = "4. Lorem\n1. Ipsum\n9. Dolor";
88
-		let expected = '<ol start="4"> <li>Lorem</li> <li>Ipsum</li> <li>Dolor</li> </ol>';
88
+		let expected = '<ol start="4"><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ol>';
89 89
 		let actual = this.md(markdown);
90
-		this.assertEqual(actual, expected);
90
+		this.assertEqual(expected, actual);
91 91
 	}
92 92
 
93 93
 	test_orderedList_nested1() {
94 94
 		let markdown = "1. Lorem\n 1. Ipsum\n1. Dolor";
95
-		let expected = '<ol> <li>Lorem<ol> <li>Ipsum</li> </ol> </li> <li>Dolor</li> </ol>';
95
+		let expected = '<ol><li>Lorem<ol><li>Ipsum</li></ol></li><li>Dolor</li></ol>';
96 96
 		let actual = this.md(markdown);
97
-		this.assertEqual(actual, expected);
97
+		this.assertEqual(expected, actual);
98 98
 	}
99 99
 
100 100
 	test_orderedList_nested2() {
101 101
 		let markdown = "1. Lorem\n 1. Ipsum\n      1. Dolor\n 1. Sit\n1. Amet";
102
-		let expected = '<ol> <li>Lorem<ol> <li>Ipsum<ol> <li>Dolor</li> </ol> </li> <li>Sit</li> </ol> </li> <li>Amet</li> </ol>';
102
+		let expected = '<ol><li>Lorem<ol><li>Ipsum<ol><li>Dolor</li></ol></li><li>Sit</li></ol></li><li>Amet</li></ol>';
103 103
 		let actual = this.md(markdown);
104
-		this.assertEqual(actual, expected);
104
+		this.assertEqual(expected, actual);
105 105
 	}
106 106
 
107 107
 	test_blockquote() {
108 108
 		let markdown = '> Lorem ipsum dolor';
109 109
 		let expected = '<blockquote>Lorem ipsum dolor</blockquote>';
110 110
 		let actual = this.md(markdown);
111
-		this.assertEqual(actual, expected);
111
+		this.assertEqual(expected, actual);
112 112
 	}
113 113
 
114 114
 	test_blockquote_paragraphs() {
115 115
 		let markdown = '> Lorem ipsum dolor\n>\n>Sit amet';
116
-		let expected = '<blockquote> <p>Lorem ipsum dolor</p> <p>Sit amet</p> </blockquote>';
116
+		let expected = '<blockquote><p>Lorem ipsum dolor</p><p>Sit amet</p></blockquote>';
117 117
 		let actual = this.md(markdown);
118
-		this.assertEqual(actual, expected);
118
+		this.assertEqual(expected, actual);
119 119
 	}
120 120
 
121 121
 	test_blockquote_list() {
122 122
 		let markdown = '> 1. Lorem\n> 2. Ipsum';
123
-		let expected = '<blockquote> <ol> <li>Lorem</li> <li>Ipsum</li> </ol> </blockquote>';
123
+		let expected = '<blockquote><ol><li>Lorem</li><li>Ipsum</li></ol></blockquote>';
124 124
 		let actual = this.md(markdown);
125
-		this.assertEqual(actual, expected);
125
+		this.assertEqual(expected, actual);
126 126
 	}
127 127
 
128 128
 	test_codeBlock_indented() {
129 129
 		let markdown = "Code\n\n    function foo() {\n        return 'bar';\n    }\n\nend";
130 130
 		let expected = "<p>Code</p>\n\n<pre><code>function foo() {\n    return 'bar';\n}</code></pre>\n\n<p>end</p>";
131 131
 		let actual = this.parser.toHTML(markdown).trim(); // don't normalize whitespace
132
-		this.assertEqual(actual.replace(/ /g, '⎵'), expected.replace(/ /g, '⎵'));
132
+		this.assertEqual(expected.replace(/ /g, '⎵'), actual.replace(/ /g, '⎵'));
133 133
 	}
134 134
 
135 135
 	test_codeBlock_fenced() {
136 136
 		let markdown = "Code\n\n```\nfunction foo() {\n    return 'bar';\n}\n```\n\nend";
137 137
 		let expected = "<p>Code</p>\n\n<pre><code>function foo() {\n    return 'bar';\n}</code></pre>\n\n<p>end</p>";
138 138
 		let actual = this.parser.toHTML(markdown).trim(); // don't normalize whitespace
139
-		this.assertEqual(actual.replace(/ /g, '⎵'), expected.replace(/ /g, '⎵'));
139
+		this.assertEqual(expected.replace(/ /g, '⎵'), actual.replace(/ /g, '⎵'));
140 140
 	}
141 141
 
142 142
 	test_codeBlock_fenced_language() {
143 143
 		let markdown = "Code\n\n```javascript\nfunction foo() {\n    return 'bar';\n}\n```\n\nend";
144 144
 		let expected = "<p>Code</p>\n\n<pre><code class=\"language-javascript\">function foo() {\n    return 'bar';\n}</code></pre>\n\n<p>end</p>";
145 145
 		let actual = this.parser.toHTML(markdown).trim(); // don't normalize whitespace
146
-		this.assertEqual(actual.replace(/ /g, '⎵'), expected.replace(/ /g, '⎵'));
146
+		this.assertEqual(expected.replace(/ /g, '⎵'), actual.replace(/ /g, '⎵'));
147 147
 	}
148 148
 
149 149
 	test_horizontalRule() {
150 150
 		let markdown = "Before\n\n---\n\n- - -\n\n***\n\n* * * * * * *\n\nafter";
151
-		let expected = "<p>Before</p> <hr> <hr> <hr> <hr> <p>after</p>";
151
+		let expected = "<p>Before</p><hr><hr><hr><hr><p>after</p>";
152 152
 		let actual = this.md(markdown);
153
-		this.assertEqual(actual, expected);
153
+		this.assertEqual(expected, actual);
154 154
 	}
155 155
 
156 156
 	test_table_unfenced() {
157 157
 		let markdown = "Column A | Column B | Column C\n--- | --- | ---\n1 | 2 | 3\n4 | 5 | 6";
158
-		let expected = "<table> <thead> <tr> <th>Column A</th> <th>Column B</th> <th>Column C</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> <tr> <td>4</td> <td>5</td> <td>6</td> </tr> </tbody> </table>";
158
+		let expected = "<table><thead><tr><th>Column A</th><th>Column B</th><th>Column C</th></tr></thead><tbody><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr></tbody></table>";
159 159
 		let actual = this.md(markdown);
160
-		this.assertEqual(actual, expected);
160
+		this.assertEqual(expected, actual);
161 161
 	}
162 162
 
163 163
 	test_table_fenced() {
164 164
 		let markdown = "| Column A | Column B | Column C |\n| --- | --- | --- |\n| 1 | 2 | 3\n4 | 5 | 6 |";
165
-		let expected = "<table> <thead> <tr> <th>Column A</th> <th>Column B</th> <th>Column C</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> <tr> <td>4</td> <td>5</td> <td>6</td> </tr> </tbody> </table>";
165
+		let expected = "<table><thead><tr><th>Column A</th><th>Column B</th><th>Column C</th></tr></thead><tbody><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr></tbody></table>";
166 166
 		let actual = this.md(markdown);
167
-		this.assertEqual(actual, expected);
167
+		this.assertEqual(expected, actual);
168 168
 	}
169 169
 
170 170
 	test_table_alignment() {
@@ -172,29 +172,29 @@ class BlockTests extends BaseTest {
172 172
 			':--- | :---: | ---:\n' +
173 173
 			'1 | 2 | 3\n' +
174 174
 			'4 | 5 | 6';
175
-		let expected = '<table> ' +
176
-			'<thead> ' +
177
-			'<tr> ' +
178
-			'<th style="text-align: left;">Column A</th> ' +
179
-			'<th style="text-align: center;">Column B</th> ' +
180
-			'<th style="text-align: right;">Column C</th> ' +
181
-			'</tr> ' +
182
-			'</thead> ' +
183
-			'<tbody> ' +
184
-			'<tr> ' +
185
-			'<td style="text-align: left;">1</td> ' +
186
-			'<td style="text-align: center;">2</td> ' +
187
-			'<td style="text-align: right;">3</td> ' +
188
-			'</tr> ' +
189
-			'<tr> ' +
190
-			'<td style="text-align: left;">4</td> ' +
191
-			'<td style="text-align: center;">5</td> ' +
192
-			'<td style="text-align: right;">6</td> ' +
193
-			'</tr> ' +
194
-			'</tbody> ' +
175
+		let expected = '<table>' +
176
+			'<thead>' +
177
+			'<tr>' +
178
+			'<th style="text-align: left;">Column A</th>' +
179
+			'<th style="text-align: center;">Column B</th>' +
180
+			'<th style="text-align: right;">Column C</th>' +
181
+			'</tr>' +
182
+			'</thead>' +
183
+			'<tbody>' +
184
+			'<tr>' +
185
+			'<td style="text-align: left;">1</td>' +
186
+			'<td style="text-align: center;">2</td>' +
187
+			'<td style="text-align: right;">3</td>' +
188
+			'</tr>' +
189
+			'<tr>' +
190
+			'<td style="text-align: left;">4</td>' +
191
+			'<td style="text-align: center;">5</td>' +
192
+			'<td style="text-align: right;">6</td>' +
193
+			'</tr>' +
194
+			'</tbody>' +
195 195
 			'</table>';
196 196
 		let actual = this.md(markdown);
197
-		this.assertEqual(actual, expected);
197
+		this.assertEqual(expected, actual);
198 198
 	}
199 199
 
200 200
 	test_table_holes() {
@@ -203,34 +203,34 @@ class BlockTests extends BaseTest {
203 203
 			'|1|2||\n' +
204 204
 			'|4||6|\n' +
205 205
 			'||8|9|';
206
-		let expected = '<table> ' +
207
-			'<thead> ' +
208
-			'<tr> ' +
209
-			'<th>Column A</th> ' +
210
-			'<th></th> ' +
211
-			'<th>Column C</th> ' +
212
-			'</tr> ' +
213
-			'</thead> ' +
214
-			'<tbody> ' +
215
-			'<tr> ' +
216
-			'<td>1</td> ' +
217
-			'<td>2</td> ' +
218
-			'<td></td> ' +
219
-			'</tr> ' +
220
-			'<tr> ' +
221
-			'<td>4</td> ' +
222
-			'<td></td> ' +
223
-			'<td>6</td> ' +
224
-			'</tr> ' +
225
-			'<tr> ' +
226
-			'<td></td> ' +
227
-			'<td>8</td> ' +
228
-			'<td>9</td> ' +
229
-			'</tr> ' +
230
-			'</tbody> ' +
206
+		let expected = '<table>' +
207
+			'<thead>' +
208
+			'<tr>' +
209
+			'<th>Column A</th>' +
210
+			'<th></th>' +
211
+			'<th>Column C</th>' +
212
+			'</tr>' +
213
+			'</thead>' +
214
+			'<tbody>' +
215
+			'<tr>' +
216
+			'<td>1</td>' +
217
+			'<td>2</td>' +
218
+			'<td></td>' +
219
+			'</tr>' +
220
+			'<tr>' +
221
+			'<td>4</td>' +
222
+			'<td></td>' +
223
+			'<td>6</td>' +
224
+			'</tr>' +
225
+			'<tr>' +
226
+			'<td></td>' +
227
+			'<td>8</td>' +
228
+			'<td>9</td>' +
229
+			'</tr>' +
230
+			'</tbody>' +
231 231
 			'</table>';
232 232
 		let actual = this.md(markdown);
233
-		this.assertEqual(actual, expected);
233
+		this.assertEqual(expected, actual);
234 234
 	}
235 235
 
236 236
 	test_definitionList() {
@@ -241,30 +241,30 @@ class BlockTests extends BaseTest {
241 241
 			': def 1\n' +
242 242
 			' broken on next line\n' +
243 243
 			': def 2';
244
-		let expected = '<dl> ' +
245
-			'<dt>term</dt> ' +
246
-			'<dd>definition</dd> ' +
247
-			'<dt>another term</dt> ' +
248
-			'<dd>def 1 broken on next line</dd> ' +
249
-			'<dd>def 2</dd> ' +
244
+		let expected = '<dl>' +
245
+			'<dt>term</dt>' +
246
+			'<dd>definition</dd>' +
247
+			'<dt>another term</dt>' +
248
+			'<dd>def 1 broken on next line</dd>' +
249
+			'<dd>def 2</dd>' +
250 250
 			'</dl>';
251 251
 		let actual = this.md(markdown);
252
-		this.assertEqual(actual, expected);
252
+		this.assertEqual(expected, actual);
253 253
 	}
254 254
 
255 255
 	test_footnotes() {
256 256
 		let markdown = 'Lorem ipsum[^1] dolor[^abc] sit[^1] amet\n\n[^1]: A footnote\n[^abc]: Another footnote';
257 257
 		let expected = '<p>Lorem ipsum<sup class="footnote" id="footnoteref_1"><a href="#footnote_1">1</a></sup> ' +
258 258
 			'dolor<sup class="footnote" id="footnoteref_2"><a href="#footnote_2">2</a></sup> ' +
259
-			'sit<sup class="footnote" id="footnoteref_3"><a href="#footnote_1">1</a></sup> amet</p> ' +
259
+			'sit<sup class="footnote" id="footnoteref_3"><a href="#footnote_1">1</a></sup> amet</p>' +
260 260
 			'<div class="footnotes">' +
261 261
 			'<ol>' +
262
-			'<li value="1" id="footnote_1">A footnote <a href="#footnoteref_1" class="footnote-backref">↩︎</a> <a href="#footnoteref_3" class="footnote-backref">↩︎</a></li> ' +
263
-			'<li value="2" id="footnote_2">Another footnote <a href="#footnoteref_2" class="footnote-backref">↩︎</a></li> ' +
262
+			'<li value="1" id="footnote_1">A footnote <a href="#footnoteref_1" class="footnote-backref">↩︎</a><a href="#footnoteref_3" class="footnote-backref">↩︎</a></li>' +
263
+			'<li value="2" id="footnote_2">Another footnote <a href="#footnoteref_2" class="footnote-backref">↩︎</a></li>' +
264 264
 			'</ol>' +
265 265
 			'</div>';
266 266
 		let actual = this.md(markdown);
267
-		this.assertEqual(actual, expected);
267
+		this.assertEqual(expected, actual);
268 268
 	}
269 269
 
270 270
 	test_abbreviations() {
@@ -273,6 +273,6 @@ class BlockTests extends BaseTest {
273 273
 			'*[HTML]: Hypertext Markup Language';
274 274
 		let expected = '<p>Lorem ipsum <abbr title="Hypertext Markup Language">HTML</abbr> dolor <abbr title="Hypertext Markup Language">HTML</abbr> sit</p>';
275 275
 		let actual = this.md(markdown);
276
-		this.assertEqual(actual, expected);
276
+		this.assertEqual(expected, actual);
277 277
 	}
278 278
 }

+ 32
- 32
jstest/InlineTests.js 查看文件

@@ -13,210 +13,210 @@ class InlineTests extends BaseTest {
13 13
 		let markdown = 'Lorem ipsum';
14 14
 		let expected = 'Lorem ipsum';
15 15
 		let actual = this.md(markdown);
16
-		this.assertEqual(actual, expected);
16
+		this.assertEqual(expected, actual);
17 17
 	}
18 18
 
19 19
 	test_strong() {
20 20
 		let markdown = 'Lorem **ipsum** dolor **sit**';
21 21
 		let expected = 'Lorem <strong>ipsum</strong> dolor <strong>sit</strong>';
22 22
 		let actual = this.md(markdown);
23
-		this.assertEqual(actual, expected);
23
+		this.assertEqual(expected, actual);
24 24
 	}
25 25
 
26 26
 	test_emphasis() {
27 27
 		let markdown = 'Lorem _ipsum_ dolor _sit_';
28 28
 		let expected = 'Lorem <em>ipsum</em> dolor <em>sit</em>';
29 29
 		let actual = this.md(markdown);
30
-		this.assertEqual(actual, expected);
30
+		this.assertEqual(expected, actual);
31 31
 	}
32 32
 
33 33
 	test_strongEmphasis_cleanNesting1() {
34 34
 		let markdown = 'Lorem **ipsum *dolor* sit** amet';
35 35
 		let expected = 'Lorem <strong>ipsum <em>dolor</em> sit</strong> amet';
36 36
 		let actual = this.md(markdown);
37
-		this.assertEqual(actual, expected);
37
+		this.assertEqual(expected, actual);
38 38
 	}
39 39
 
40 40
 	test_strongEmphasis_cleanNesting2() {
41 41
 		let markdown = 'Lorem *ipsum **dolor** sit* amet';
42 42
 		let expected = 'Lorem <em>ipsum <strong>dolor</strong> sit</em> amet';
43 43
 		let actual = this.md(markdown);
44
-		this.assertEqual(actual, expected);
44
+		this.assertEqual(expected, actual);
45 45
 	}
46 46
 
47 47
 	test_strongEmphasis_tightNesting() {
48 48
 		let markdown = 'Lorem ***ipsum*** dolor';
49 49
 		let expected = 'Lorem <strong><em>ipsum</em></strong> dolor';
50 50
 		let actual = this.md(markdown);
51
-		this.assertEqual(actual, expected);
51
+		this.assertEqual(expected, actual);
52 52
 	}
53 53
 
54 54
 	test_strongEmphasis_lopsidedNesting1() {
55 55
 		let markdown = 'Lorem ***ipsum* dolor** sit';
56 56
 		let expected = 'Lorem <strong><em>ipsum</em> dolor</strong> sit';
57 57
 		let actual = this.md(markdown);
58
-		this.assertEqual(actual, expected);
58
+		this.assertEqual(expected, actual);
59 59
 	}
60 60
 
61 61
 	test_strongEmphasis_lopsidedNesting2() {
62 62
 		let markdown = 'Lorem ***ipsum** dolor* sit';
63 63
 		let expected = 'Lorem <em><strong>ipsum</strong> dolor</em> sit';
64 64
 		let actual = this.md(markdown);
65
-		this.assertEqual(actual, expected);
65
+		this.assertEqual(expected, actual);
66 66
 	}
67 67
 
68 68
 	test_strongEmphasis_lopsidedNesting3() {
69 69
 		let markdown = 'Lorem **ipsum *dolor*** sit';
70 70
 		let expected = 'Lorem <strong>ipsum <em>dolor</em></strong> sit';
71 71
 		let actual = this.md(markdown);
72
-		this.assertEqual(actual, expected);
72
+		this.assertEqual(expected, actual);
73 73
 	}
74 74
 
75 75
 	test_strongEmphasis_lopsidedNesting4() {
76 76
 		let markdown = 'Lorem *ipsum **dolor*** sit';
77 77
 		let expected = 'Lorem <em>ipsum <strong>dolor</strong></em> sit';
78 78
 		let actual = this.md(markdown);
79
-		this.assertEqual(actual, expected);
79
+		this.assertEqual(expected, actual);
80 80
 	}
81 81
 
82 82
 	test_inlineCode() {
83 83
 		let markdown = 'Lorem `ipsum` dolor';
84 84
 		let expected = 'Lorem <code>ipsum</code> dolor';
85 85
 		let actual = this.md(markdown);
86
-		this.assertEqual(actual, expected);
86
+		this.assertEqual(expected, actual);
87 87
 	}
88 88
 
89 89
 	test_inlineCode_withInnerBacktick() {
90 90
 		let markdown = 'Lorem ``ip`su`m`` dolor';
91 91
 		let expected = 'Lorem <code>ip`su`m</code> dolor';
92 92
 		let actual = this.md(markdown);
93
-		this.assertEqual(actual, expected);
93
+		this.assertEqual(expected, actual);
94 94
 	}
95 95
 
96 96
 	test_strikethrough_double() {
97 97
 		let markdown = 'Lorem ~~ipsum~~ dolor';
98 98
 		let expected = 'Lorem <s>ipsum</s> dolor';
99 99
 		let actual = this.md(markdown);
100
-		this.assertEqual(actual, expected);
100
+		this.assertEqual(expected, actual);
101 101
 	}
102 102
 
103 103
 	test_subscript() {
104 104
 		let markdown = 'H~2~O';
105 105
 		let expected = 'H<sub>2</sub>O';
106 106
 		let actual = this.md(markdown);
107
-		this.assertEqual(actual, expected);
107
+		this.assertEqual(expected, actual);
108 108
 	}
109 109
 
110 110
 	test_superscript() {
111 111
 		let markdown = 'E=mc^2^';
112 112
 		let expected = 'E=mc<sup>2</sup>';
113 113
 		let actual = this.md(markdown);
114
-		this.assertEqual(actual, expected);
114
+		this.assertEqual(expected, actual);
115 115
 	}
116 116
 
117 117
 	test_highlight() {
118 118
 		let markdown = 'Lorem ==ipsum== dolor';
119 119
 		let expected = 'Lorem <mark>ipsum</mark> dolor';
120 120
 		let actual = this.md(markdown);
121
-		this.assertEqual(actual, expected);
121
+		this.assertEqual(expected, actual);
122 122
 	}
123 123
 
124 124
 	test_underline() {
125 125
 		let markdown = 'Lorem __ipsum__ dolor';
126 126
 		let expected = 'Lorem <u>ipsum</u> dolor';
127 127
 		let actual = this.md(markdown);
128
-		this.assertEqual(actual, expected);
128
+		this.assertEqual(expected, actual);
129 129
 	}
130 130
 
131 131
 	test_link_fullyQualified() {
132 132
 		let markdown = 'Lorem [ipsum](https://example.com/path/page.html) dolor';
133 133
 		let expected = 'Lorem <a href="https://example.com/path/page.html">ipsum</a> dolor';
134 134
 		let actual = this.md(markdown);
135
-		this.assertEqual(actual, expected);
135
+		this.assertEqual(expected, actual);
136 136
 	}
137 137
 
138 138
 	test_link_relative() {
139 139
 		let markdown = 'Lorem [ipsum](page.html) dolor';
140 140
 		let expected = 'Lorem <a href="page.html">ipsum</a> dolor';
141 141
 		let actual = this.md(markdown);
142
-		this.assertEqual(actual, expected);
142
+		this.assertEqual(expected, actual);
143 143
 	}
144 144
 
145 145
 	test_link_title() {
146 146
 		let markdown = 'Lorem [ipsum](page.html "link title") dolor';
147 147
 		let expected = 'Lorem <a href="page.html" title="link title">ipsum</a> dolor';
148 148
 		let actual = this.md(markdown);
149
-		this.assertEqual(actual, expected);
149
+		this.assertEqual(expected, actual);
150 150
 	}
151 151
 
152 152
 	test_link_literal() {
153 153
 		let markdown = 'Lorem <https://example.com> dolor';
154 154
 		let expected = 'Lorem <a href="https://example.com">https://example.com</a> dolor';
155 155
 		let actual = this.md(markdown);
156
-		this.assertEqual(actual, expected);
156
+		this.assertEqual(expected, actual);
157 157
 	}
158 158
 
159 159
 	test_link_ref() {
160 160
 		let markdown = "Lorem [ipsum][ref] dolor\n\n[ref]: https://example.com";
161 161
 		let expected = '<p>Lorem <a href="https://example.com">ipsum</a> dolor</p>';
162 162
 		let actual = this.md(markdown);
163
-		this.assertEqual(actual, expected);
163
+		this.assertEqual(expected, actual);
164 164
 	}
165 165
 
166 166
 	test_link_email() {
167 167
 		let markdown = 'Lorem [ipsum](user@example.com) dolor';
168 168
 		let expected = 'Lorem <a href="mailto:&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;">ipsum</a> dolor';
169 169
 		let actual = this.md(markdown);
170
-		this.assertEqual(actual, expected);
170
+		this.assertEqual(expected, actual);
171 171
 	}
172 172
 
173 173
 	test_link_email_withTitle() {
174 174
 		let markdown = 'Lorem [ipsum](user@example.com "title") dolor';
175 175
 		let expected = 'Lorem <a href="mailto:&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;" title="title">ipsum</a> dolor';
176 176
 		let actual = this.md(markdown);
177
-		this.assertEqual(actual, expected);
177
+		this.assertEqual(expected, actual);
178 178
 	}
179 179
 
180 180
 	test_link_literalEmail() {
181 181
 		let markdown = 'Lorem <user@example.com> dolor';
182 182
 		let expected = 'Lorem <a href="mailto:&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;">&#117;&#115;&#101;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;</a> dolor';
183 183
 		let actual = this.md(markdown);
184
-		this.assertEqual(actual, expected);
184
+		this.assertEqual(expected, actual);
185 185
 	}
186 186
 
187 187
 	test_link_image() {
188 188
 		let markdown = 'Lorem [![alt](image.jpg)](page.html) ipsum';
189 189
 		let expected = 'Lorem <a href="page.html"><img src="image.jpg" alt="alt"></a> ipsum';
190 190
 		let actual = this.md(markdown);
191
-		this.assertEqual(actual, expected);
191
+		this.assertEqual(expected, actual);
192 192
 	}
193 193
 
194 194
 	test_link_image_complex() {
195 195
 		let markdown = 'Lorem [![alt] (image.jpg "image title")] (page.html "link title") ipsum';
196 196
 		let expected = 'Lorem <a href="page.html" title="link title"><img src="image.jpg" alt="alt" title="image title"></a> ipsum';
197 197
 		let actual = this.md(markdown);
198
-		this.assertEqual(actual, expected);
198
+		this.assertEqual(expected, actual);
199 199
 	}
200 200
 
201 201
 	test_image() {
202 202
 		let markdown = 'Lorem ![alt text](image.jpg) dolor';
203 203
 		let expected = 'Lorem <img src="image.jpg" alt="alt text"> dolor';
204 204
 		let actual = this.md(markdown);
205
-		this.assertEqual(actual, expected);
205
+		this.assertEqual(expected, actual);
206 206
 	}
207 207
 
208 208
 	test_image_noAlt() {
209 209
 		let markdown = 'Lorem ![](image.jpg) dolor';
210 210
 		let expected = 'Lorem <img src="image.jpg"> dolor';
211 211
 		let actual = this.md(markdown);
212
-		this.assertEqual(actual, expected);
212
+		this.assertEqual(expected, actual);
213 213
 	}
214 214
 
215 215
 	test_image_withTitle() {
216 216
 		let markdown = 'Lorem ![alt text](image.jpg "image title") dolor';
217 217
 		let expected = 'Lorem <img src="image.jpg" alt="alt text" title="image title"> dolor';
218 218
 		let actual = this.md(markdown);
219
-		this.assertEqual(actual, expected);
219
+		this.assertEqual(expected, actual);
220 220
 	}
221 221
 
222 222
 	test_image_ref() {
@@ -224,13 +224,13 @@ class InlineTests extends BaseTest {
224 224
 			'[ref]: image.jpg "image title"';
225 225
 		let expected = '<p>Lorem <img src="image.jpg" alt="alt text" title="image title"> dolor</p>';
226 226
 		let actual = this.md(markdown);
227
-		this.assertEqual(actual, expected);
227
+		this.assertEqual(expected, actual);
228 228
 	}
229 229
 
230 230
 	test_htmlTags() {
231 231
 		let markdown = 'Lorem <strong title=\'with " quote\' id="with \' apostrophe" lang=unquoted translate forbidden="true">ipsum</strong> dolor';
232 232
 		let expected = 'Lorem <strong title="with &quot; quote" id="with \' apostrophe" lang="unquoted" translate>ipsum</strong> dolor';
233 233
 		let actual = this.md(markdown);
234
-		this.assertEqual(actual, expected);
234
+		this.assertEqual(expected, actual);
235 235
 	}
236 236
 }

+ 8
- 8
jstest/TokenTests.js 查看文件

@@ -15,12 +15,12 @@ class TokenTests extends BaseTest {
15 15
 		const pattern = [
16 16
 			MDTokenType.Underscore,
17 17
 		];
18
-		const result = MDToken.findFirstTokens(tokens, pattern);
18
+		const actual = MDToken.findFirstTokens(tokens, pattern);
19 19
 		const expected = {
20 20
 			tokens: [ tokens[2] ],
21 21
 			index: 2,
22 22
 		};
23
-		this.assertEqual(result, expected);
23
+		this.assertEqual(expected, actual);
24 24
 	}
25 25
 
26 26
 	test_findFirstTokens_optionalWhitespace1() {
@@ -37,12 +37,12 @@ class TokenTests extends BaseTest {
37 37
 			MDTokenType.META_OptionalWhitespace,
38 38
 			MDTokenType.URL,
39 39
 		];
40
-		const result = MDToken.findFirstTokens(tokens, pattern);
40
+		const actual = MDToken.findFirstTokens(tokens, pattern);
41 41
 		const expected = {
42 42
 			tokens: [ tokens[2], tokens[3] ],
43 43
 			index: 2,
44 44
 		};
45
-		this.assertEqual(result, expected);
45
+		this.assertEqual(expected, actual);
46 46
 	}
47 47
 
48 48
 	test_findFirstTokens_optionalWhitespace2() {
@@ -60,12 +60,12 @@ class TokenTests extends BaseTest {
60 60
 			MDTokenType.META_OptionalWhitespace,
61 61
 			MDTokenType.URL,
62 62
 		];
63
-		const result = MDToken.findFirstTokens(tokens, pattern);
63
+		const actual = MDToken.findFirstTokens(tokens, pattern);
64 64
 		const expected = {
65 65
 			tokens: [ tokens[2], tokens[3], tokens[4] ],
66 66
 			index: 2,
67 67
 		};
68
-		this.assertEqual(result, expected);
68
+		this.assertEqual(expected, actual);
69 69
 	}
70 70
 
71 71
 	test_findPairedTokens() {
@@ -84,7 +84,7 @@ class TokenTests extends BaseTest {
84 84
 		const pattern = [
85 85
 			MDTokenType.Underscore,
86 86
 		];
87
-		const result = MDToken.findPairedTokens(tokens, pattern, pattern);
87
+		const actual = MDToken.findPairedTokens(tokens, pattern, pattern);
88 88
 		const expected = {
89 89
 			startTokens: [ tokens[2] ],
90 90
 			contentTokens: [ tokens[3] ],
@@ -94,6 +94,6 @@ class TokenTests extends BaseTest {
94 94
 			endIndex: 4,
95 95
 			totalLength: 3,
96 96
 		}
97
-		this.assertEqual(result, expected);
97
+		this.assertEqual(expected, actual);
98 98
 	}
99 99
 }

+ 63
- 63
jstest/UtilsTests.js 查看文件

@@ -1,84 +1,84 @@
1 1
 class UtilsTests extends BaseTest {
2 2
 	test_stripIndent() {
3
-		this.assertEqual(MDUtils.stripIndent(''), '');
4
-		this.assertEqual(MDUtils.stripIndent('  '), '');
5
-		this.assertEqual(MDUtils.stripIndent('foo'), 'foo');
6
-		this.assertEqual(MDUtils.stripIndent(' foo'), 'foo');
7
-		this.assertEqual(MDUtils.stripIndent('  foo'), 'foo');
8
-		this.assertEqual(MDUtils.stripIndent('   foo'), 'foo');
9
-		this.assertEqual(MDUtils.stripIndent('    foo'), 'foo');
10
-		this.assertEqual(MDUtils.stripIndent('     foo'), ' foo');
11
-		this.assertEqual(MDUtils.stripIndent('\tfoo'), 'foo');
12
-		this.assertEqual(MDUtils.stripIndent('\t\tfoo'), '\tfoo');
13
-		this.assertEqual(MDUtils.stripIndent('\t\tfoo', 2), 'foo');
14
-		this.assertEqual(MDUtils.stripIndent('      foo', 2), 'foo');
3
+		this.assertEqual('', MDUtils.stripIndent(''));
4
+		this.assertEqual('', MDUtils.stripIndent('  '));
5
+		this.assertEqual('foo', MDUtils.stripIndent('foo'));
6
+		this.assertEqual('foo', MDUtils.stripIndent(' foo'));
7
+		this.assertEqual('foo', MDUtils.stripIndent('  foo'));
8
+		this.assertEqual('foo', MDUtils.stripIndent('   foo'));
9
+		this.assertEqual('foo', MDUtils.stripIndent('    foo'));
10
+		this.assertEqual(' foo', MDUtils.stripIndent('     foo'));
11
+		this.assertEqual('foo', MDUtils.stripIndent('\tfoo'));
12
+		this.assertEqual("\tfoo", MDUtils.stripIndent('\t\tfoo'));
13
+		this.assertEqual('foo', MDUtils.stripIndent('\t\tfoo', 2));
14
+		this.assertEqual('foo', MDUtils.stripIndent('      foo', 2));
15 15
 	}
16 16
 
17 17
 	test_countIndents() {
18
-		this.assertEqual(MDUtils.countIndents(''), 0);
19
-		this.assertEqual(MDUtils.countIndents('  '), 1);
20
-		this.assertEqual(MDUtils.countIndents('    '), 1);
21
-		this.assertEqual(MDUtils.countIndents('foo'), 0);
22
-		this.assertEqual(MDUtils.countIndents('foo'), 0);
23
-		this.assertEqual(MDUtils.countIndents(' foo'), 1);
24
-		this.assertEqual(MDUtils.countIndents('  foo'), 1);
25
-		this.assertEqual(MDUtils.countIndents('   foo'), 1);
26
-		this.assertEqual(MDUtils.countIndents('    foo'), 1);
27
-		this.assertEqual(MDUtils.countIndents('     foo'), 2);
28
-		this.assertEqual(MDUtils.countIndents('\tfoo'), 1);
29
-		this.assertEqual(MDUtils.countIndents('\t\tfoo'), 2);
18
+		this.assertEqual(0, MDUtils.countIndents(''));
19
+		this.assertEqual(1, MDUtils.countIndents('  '));
20
+		this.assertEqual(1, MDUtils.countIndents('    '));
21
+		this.assertEqual(0, MDUtils.countIndents('foo'));
22
+		this.assertEqual(0, MDUtils.countIndents('foo'));
23
+		this.assertEqual(1, MDUtils.countIndents(' foo'));
24
+		this.assertEqual(1, MDUtils.countIndents('  foo'));
25
+		this.assertEqual(1, MDUtils.countIndents('   foo'));
26
+		this.assertEqual(1, MDUtils.countIndents('    foo'));
27
+		this.assertEqual(2, MDUtils.countIndents('     foo'));
28
+		this.assertEqual(1, MDUtils.countIndents('\tfoo'));
29
+		this.assertEqual(2, MDUtils.countIndents('\t\tfoo'));
30 30
 
31
-		this.assertEqual(MDUtils.countIndents('', true), 0);
32
-		this.assertEqual(MDUtils.countIndents('  ', true), 0);
33
-		this.assertEqual(MDUtils.countIndents('    ', true), 1);
34
-		this.assertEqual(MDUtils.countIndents('foo', true), 0);
35
-		this.assertEqual(MDUtils.countIndents(' foo', true), 0);
36
-		this.assertEqual(MDUtils.countIndents('  foo', true), 0);
37
-		this.assertEqual(MDUtils.countIndents('   foo', true), 0);
38
-		this.assertEqual(MDUtils.countIndents('    foo', true), 1);
39
-		this.assertEqual(MDUtils.countIndents('     foo', true), 1);
40
-		this.assertEqual(MDUtils.countIndents('\tfoo', true), 1);
41
-		this.assertEqual(MDUtils.countIndents('\t\tfoo', true), 2);
31
+		this.assertEqual(0, MDUtils.countIndents('', true));
32
+		this.assertEqual(0, MDUtils.countIndents('  ', true));
33
+		this.assertEqual(1, MDUtils.countIndents('    ', true));
34
+		this.assertEqual(0, MDUtils.countIndents('foo', true));
35
+		this.assertEqual(0, MDUtils.countIndents(' foo', true));
36
+		this.assertEqual(0, MDUtils.countIndents('  foo', true));
37
+		this.assertEqual(0, MDUtils.countIndents('   foo', true));
38
+		this.assertEqual(1, MDUtils.countIndents('    foo', true));
39
+		this.assertEqual(1, MDUtils.countIndents('     foo', true));
40
+		this.assertEqual(1, MDUtils.countIndents('\tfoo', true));
41
+		this.assertEqual(2, MDUtils.countIndents('\t\tfoo', true));
42 42
 	}
43 43
 
44 44
 	test_tokenizeLabel() {
45 45
 		// Escapes are preserved
46
-		this.assertEqual(MDToken.tokenizeLabel('[foo] bar'), [ '[foo]', 'foo' ]);
47
-		this.assertEqual(MDToken.tokenizeLabel('[foo\\[] bar'), [ '[foo\\[]', 'foo\\[' ]);
48
-		this.assertEqual(MDToken.tokenizeLabel('[foo\\]] bar'), [ '[foo\\]]', 'foo\\]' ]);
49
-		this.assertEqual(MDToken.tokenizeLabel('[foo[]] bar'), [ '[foo[]]', 'foo[]' ]);
50
-		this.assertEqual(MDToken.tokenizeLabel('[foo\\(] bar'), [ '[foo\\(]', 'foo\\(' ]);
51
-		this.assertEqual(MDToken.tokenizeLabel('[foo\\)] bar'), [ '[foo\\)]', 'foo\\)' ]);
52
-		this.assertEqual(MDToken.tokenizeLabel('[foo()] bar'), [ '[foo()]', 'foo()' ]);
46
+		this.assertEqual([ '[foo]', 'foo' ], MDToken.tokenizeLabel('[foo] bar'));
47
+		this.assertEqual([ '[foo\\[]', 'foo\\[' ], MDToken.tokenizeLabel('[foo\\[] bar'));
48
+		this.assertEqual([ '[foo\\]]', 'foo\\]' ], MDToken.tokenizeLabel('[foo\\]] bar'));
49
+		this.assertEqual([ '[foo[]]', 'foo[]' ], MDToken.tokenizeLabel('[foo[]] bar'));
50
+		this.assertEqual([ '[foo\\(]', 'foo\\(' ], MDToken.tokenizeLabel('[foo\\(] bar'));
51
+		this.assertEqual([ '[foo\\)]', 'foo\\)' ], MDToken.tokenizeLabel('[foo\\)] bar'));
52
+		this.assertEqual([ '[foo()]', 'foo()' ], MDToken.tokenizeLabel('[foo()] bar'));
53 53
 
54
-		this.assertEqual(MDToken.tokenizeLabel('foo bar'), null);
55
-		this.assertEqual(MDToken.tokenizeLabel('[foo\\] bar'), null);
56
-		this.assertEqual(MDToken.tokenizeLabel('[foo bar'), null);
57
-		this.assertEqual(MDToken.tokenizeLabel('[foo[] bar'), null);
54
+		this.assertEqual(null, MDToken.tokenizeLabel('foo bar'));
55
+		this.assertEqual(null, MDToken.tokenizeLabel('[foo\\] bar'));
56
+		this.assertEqual(null, MDToken.tokenizeLabel('[foo bar'));
57
+		this.assertEqual(null, MDToken.tokenizeLabel('[foo[] bar'));
58 58
 	}
59 59
 
60 60
 	test_tokenizeURL() {
61
-		this.assertEqual(MDToken.tokenizeURL('(page.html) foo'), [ '(page.html)', 'page.html', null ]);
62
-		this.assertEqual(MDToken.tokenizeURL('(page.html "link title") foo'), [ '(page.html "link title")', 'page.html', 'link title' ]);
63
-		this.assertEqual(MDToken.tokenizeURL('(https://example.com/path/page.html?query=foo&bar=baz#fragment) foo'), [ '(https://example.com/path/page.html?query=foo&bar=baz#fragment)', 'https://example.com/path/page.html?query=foo&bar=baz#fragment', null ]);
61
+		this.assertEqual([ '(page.html)', 'page.html', null ], MDToken.tokenizeURL('(page.html) foo'));
62
+		this.assertEqual([ '(page.html "link title")', 'page.html', 'link title' ], MDToken.tokenizeURL('(page.html "link title") foo'));
63
+		this.assertEqual([ '(https://example.com/path/page.html?query=foo&bar=baz#fragment)', 'https://example.com/path/page.html?query=foo&bar=baz#fragment', null ], MDToken.tokenizeURL('(https://example.com/path/page.html?query=foo&bar=baz#fragment) foo'));
64 64
 
65
-		this.assertEqual(MDToken.tokenizeURL('page.html foo'), null);
66
-		this.assertEqual(MDToken.tokenizeURL('(page.html foo'), null);
67
-		this.assertEqual(MDToken.tokenizeURL('page.html) foo'), null);
68
-		this.assertEqual(MDToken.tokenizeURL('(page.html "title) foo'), null);
69
-		this.assertEqual(MDToken.tokenizeURL('(page .html) foo'), null);
70
-		this.assertEqual(MDToken.tokenizeURL('(user@example.com) foo'), null);
71
-		this.assertEqual(MDToken.tokenizeURL('(user@example.com "title") foo'), null);
65
+		this.assertEqual(null, MDToken.tokenizeURL('page.html foo'));
66
+		this.assertEqual(null, MDToken.tokenizeURL('(page.html foo'));
67
+		this.assertEqual(null, MDToken.tokenizeURL('page.html) foo'));
68
+		this.assertEqual(null, MDToken.tokenizeURL('(page.html "title) foo'));
69
+		this.assertEqual(null, MDToken.tokenizeURL('(page .html) foo'));
70
+		this.assertEqual(null, MDToken.tokenizeURL('(user@example.com) foo'));
71
+		this.assertEqual(null, MDToken.tokenizeURL('(user@example.com "title") foo'));
72 72
 	}
73 73
 
74 74
 	test_tokenizeEmail() {
75
-		this.assertEqual(MDToken.tokenizeEmail('(user@example.com)'), [ '(user@example.com)', 'user@example.com', null ]);
76
-		this.assertEqual(MDToken.tokenizeEmail('(user@example.com "link title")'), [ '(user@example.com "link title")', 'user@example.com', 'link title' ]);
75
+		this.assertEqual([ '(user@example.com)', 'user@example.com', null ], MDToken.tokenizeEmail('(user@example.com)'));
76
+		this.assertEqual([ '(user@example.com "link title")', 'user@example.com', 'link title' ], MDToken.tokenizeEmail('(user@example.com "link title")'));
77 77
 
78
-		this.assertEqual(MDToken.tokenizeEmail('(https://example.com) foo'), null);
79
-		this.assertEqual(MDToken.tokenizeEmail('(https://example.com "link title") foo'), null);
80
-		this.assertEqual(MDToken.tokenizeEmail('(user@example.com "link title) foo'), null);
81
-		this.assertEqual(MDToken.tokenizeEmail('(user@example.com foo'), null);
82
-		this.assertEqual(MDToken.tokenizeEmail('user@example.com) foo'), null);
78
+		this.assertEqual(null, MDToken.tokenizeEmail('(https://example.com) foo'));
79
+		this.assertEqual(null, MDToken.tokenizeEmail('(https://example.com "link title") foo'));
80
+		this.assertEqual(null, MDToken.tokenizeEmail('(user@example.com "link title) foo'));
81
+		this.assertEqual(null, MDToken.tokenizeEmail('(user@example.com foo'));
82
+		this.assertEqual(null, MDToken.tokenizeEmail('user@example.com) foo'));
83 83
 	}
84 84
 }

+ 7
- 7
jstest/basetest.js 查看文件

@@ -20,14 +20,14 @@ class BaseTest {
20 20
 		if (test) this.fail(failMessage || `expected false, got ${test}`);
21 21
 	}
22 22
 
23
-	assertEqual(a, b, failMessage=null) {
24
-		if (BaseTest.#equal(a, b, this.numberDifferenceRatio)) return;
25
-		const aVal = (typeof a == 'string') ? `"${a}"` : `${a}`;
26
-		const bVal = (typeof b == 'string') ? `"${b}"` : `${b}`;
27
-		if (aVal.length > 20 || bVal.length > 20) {
28
-			this.fail(failMessage || `equality failed:\n${aVal}\n!=\n${bVal}`);
23
+	assertEqual(expected, actual, failMessage=null) {
24
+		if (BaseTest.#equal(expected, actual, this.numberDifferenceRatio)) return;
25
+		const expectedStr = (typeof expected == 'string') ? `"${expected}"` : `${expected}`;
26
+		const actualStr = (typeof actual == 'string') ? `"${actual}"` : `${actual}`;
27
+		if (expectedStr.length > 20 || actualStr.length > 20) {
28
+			this.fail(failMessage || `equality failed:\nexpected:\n${expectedStr}\n!=\nactual:\n${actualStr}`);
29 29
 		} else {
30
-			this.fail(failMessage || `equality failed: ${aVal} != ${bVal}`);
30
+			this.fail(failMessage || `equality failed: expected ${expectedStr} != actual ${actualStr}`);
31 31
 		}
32 32
 	}
33 33
 

+ 8
- 8
jstest/spreadsheet/CellAddressRangeTests.js 查看文件

@@ -8,9 +8,9 @@ class CellAddressRangeTests extends BaseTest {
8 8
 			visited.push(address.name);
9 9
 			if (sanity-- < 0) break;
10 10
 		}
11
-		const result = visited.join(',');
11
+		const actual = visited.join(',');
12 12
 		const expected = 'A1,A2,A3,A4,B1,B2,B3,B4,C1,C2,C3,C4';
13
-		this.assertEqual(result, expected);
13
+		this.assertEqual(expected, actual);
14 14
 	}
15 15
 
16 16
 	test_iterator_column() {
@@ -22,9 +22,9 @@ class CellAddressRangeTests extends BaseTest {
22 22
 			visited.push(address.name);
23 23
 			if (sanity-- < 0) break;
24 24
 		}
25
-		const result = visited.join(',');
25
+		const actual = visited.join(',');
26 26
 		const expected = 'B1,B2,B3,B4,C1,C2,C3,C4';
27
-		this.assertEqual(result, expected);
27
+		this.assertEqual(expected, actual);
28 28
 	}
29 29
 
30 30
 	test_iterator_beyondBounds() {
@@ -36,9 +36,9 @@ class CellAddressRangeTests extends BaseTest {
36 36
 			visited.push(address.name);
37 37
 			if (sanity-- < 0) break;
38 38
 		}
39
-		const result = visited.join(',');
39
+		const actual = visited.join(',');
40 40
 		const expected = 'A2,A3,A4,B2,B3,B4,C2,C3,C4';
41
-		this.assertEqual(result, expected);
41
+		this.assertEqual(expected, actual);
42 42
 	}
43 43
 
44 44
 	test_iterator_outOfBounds() {
@@ -50,8 +50,8 @@ class CellAddressRangeTests extends BaseTest {
50 50
 			visited.push(address.name);
51 51
 			if (sanity-- < 0) break;
52 52
 		}
53
-		const result = visited.join(',');
53
+		const actual = visited.join(',');
54 54
 		const expected = '';
55
-		this.assertEqual(result, expected);
55
+		this.assertEqual(expected, actual);
56 56
 	}
57 57
 }

+ 135
- 135
jstest/spreadsheet/CellValueTests.js 查看文件

@@ -2,261 +2,261 @@ class CellValueTests extends BaseTest {
2 2
 	test_fromCellString_blank() {
3 3
 		var value;
4 4
 		value = CellValue.fromCellString('');
5
-		this.assertEqual(value.type, CellValue.TYPE_BLANK);
6
-		this.assertEqual(value.formattedValue, '');
7
-		this.assertEqual(value.value, null);
5
+		this.assertEqual(CellValue.TYPE_BLANK, value.type);
6
+		this.assertEqual('', value.formattedValue);
7
+		this.assertEqual(null, value.value);
8 8
 		value = CellValue.fromCellString(' ');
9
-		this.assertEqual(value.type, CellValue.TYPE_BLANK);
10
-		this.assertEqual(value.formattedValue, '');
11
-		this.assertEqual(value.value, null);
9
+		this.assertEqual(CellValue.TYPE_BLANK, value.type);
10
+		this.assertEqual('', value.formattedValue);
11
+		this.assertEqual(null, value.value);
12 12
 	}
13 13
 
14 14
 	test_fromCellString_number() {
15 15
 		var value;
16 16
 		value = CellValue.fromCellString('123');
17
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
18
-		this.assertEqual(value.formattedValue, '123');
19
-		this.assertEqual(value.value, 123);
20
-		this.assertEqual(value.decimals, 0);
17
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
18
+		this.assertEqual('123', value.formattedValue);
19
+		this.assertEqual(123, value.value);
20
+		this.assertEqual(0, value.decimals);
21 21
 		value = CellValue.fromCellString('-0');
22
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
23
-		this.assertEqual(value.formattedValue, '-0');
24
-		this.assertEqual(value.value, 0);
25
-		this.assertEqual(value.decimals, 0);
22
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
23
+		this.assertEqual('-0', value.formattedValue);
24
+		this.assertEqual(0, value.value);
25
+		this.assertEqual(0, value.decimals);
26 26
 		value = CellValue.fromCellString('1,234');
27
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
28
-		this.assertEqual(value.formattedValue, '1,234');
29
-		this.assertEqual(value.value, 1234);
30
-		this.assertEqual(value.decimals, 0);
27
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
28
+		this.assertEqual('1,234', value.formattedValue);
29
+		this.assertEqual(1234, value.value);
30
+		this.assertEqual(0, value.decimals);
31 31
 		value = CellValue.fromCellString('-1,234,567.89');
32
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
33
-		this.assertEqual(value.formattedValue, '-1,234,567.89');
34
-		this.assertEqual(value.value, -1234567.89);
35
-		this.assertEqual(value.decimals, 2);
32
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
33
+		this.assertEqual('-1,234,567.89', value.formattedValue);
34
+		this.assertEqual(-1234567.89, value.value);
35
+		this.assertEqual(2, value.decimals);
36 36
 	}
37 37
 
38 38
 	test_fromCellString_percent() {
39 39
 		var value;
40 40
 		value = CellValue.fromCellString('123%');
41
-		this.assertEqual(value.type, CellValue.TYPE_PERCENT);
42
-		this.assertEqual(value.formattedValue, '123%');
43
-		this.assertEqual(value.value, 1.23, 0.0001);
44
-		this.assertEqual(value.decimals, 0);
41
+		this.assertEqual(CellValue.TYPE_PERCENT, value.type);
42
+		this.assertEqual('123%', value.formattedValue);
43
+		this.assertEqual(1.23, value.value);
44
+		this.assertEqual(0, value.decimals);
45 45
 		value = CellValue.fromCellString('-12.3%');
46
-		this.assertEqual(value.type, CellValue.TYPE_PERCENT);
47
-		this.assertEqual(value.formattedValue, '-12.3%');
48
-		this.assertEqual(value.value, -0.123, 0.0001);
49
-		this.assertEqual(value.decimals, 1);
46
+		this.assertEqual(CellValue.TYPE_PERCENT, value.type);
47
+		this.assertEqual('-12.3%', value.formattedValue);
48
+		this.assertEqual(-0.123, value.value);
49
+		this.assertEqual(1, value.decimals);
50 50
 	}
51 51
 
52 52
 	test_fromCellString_currency() {
53 53
 		var value;
54 54
 		value = CellValue.fromCellString('$123');
55
-		this.assertEqual(value.type, CellValue.TYPE_CURRENCY);
56
-		this.assertEqual(value.formattedValue, '$123');
57
-		this.assertEqual(value.value, 123);
58
-		this.assertEqual(value.decimals, 0);
55
+		this.assertEqual(CellValue.TYPE_CURRENCY, value.type);
56
+		this.assertEqual('$123', value.formattedValue);
57
+		this.assertEqual(123, value.value);
58
+		this.assertEqual(0, value.decimals);
59 59
 		value = CellValue.fromCellString('-$12.34');
60
-		this.assertEqual(value.type, CellValue.TYPE_CURRENCY);
61
-		this.assertEqual(value.formattedValue, '-$12.34');
62
-		this.assertEqual(value.value, -12.34, 0.0001);
63
-		this.assertEqual(value.decimals, 2);
60
+		this.assertEqual(CellValue.TYPE_CURRENCY, value.type);
61
+		this.assertEqual('-$12.34', value.formattedValue);
62
+		this.assertEqual(value.value, -12.34);
63
+		this.assertEqual(2, value.decimals);
64 64
 	}
65 65
 
66 66
 	test_fromCellString_boolean() {
67 67
 		var value;
68 68
 		value = CellValue.fromCellString('true');
69
-		this.assertEqual(value.type, CellValue.TYPE_BOOLEAN);
70
-		this.assertEqual(value.formattedValue, 'TRUE');
71
-		this.assertEqual(value.value, true);
69
+		this.assertEqual(CellValue.TYPE_BOOLEAN, value.type);
70
+		this.assertEqual('TRUE', value.formattedValue);
71
+		this.assertEqual(true, value.value);
72 72
 		value = CellValue.fromCellString('false');
73
-		this.assertEqual(value.type, CellValue.TYPE_BOOLEAN);
74
-		this.assertEqual(value.formattedValue, 'FALSE');
75
-		this.assertEqual(value.value, false);
73
+		this.assertEqual(CellValue.TYPE_BOOLEAN, value.type);
74
+		this.assertEqual('FALSE', value.formattedValue);
75
+		this.assertEqual(false, value.value);
76 76
 	}
77 77
 
78 78
 	test_fromCellString_string() {
79 79
 		var value;
80 80
 		value = CellValue.fromCellString('some text');
81
-		this.assertEqual(value.type, CellValue.TYPE_STRING);
82
-		this.assertEqual(value.formattedValue, 'some text');
83
-		this.assertEqual(value.value, 'some text');
81
+		this.assertEqual(CellValue.TYPE_STRING, value.type);
82
+		this.assertEqual('some text', value.formattedValue);
83
+		this.assertEqual('some text', value.value);
84 84
 		value = CellValue.fromCellString("'0123");
85
-		this.assertEqual(value.type, CellValue.TYPE_STRING);
86
-		this.assertEqual(value.formattedValue, '0123');
87
-		this.assertEqual(value.value, '0123');
85
+		this.assertEqual(CellValue.TYPE_STRING, value.type);
86
+		this.assertEqual('0123', value.formattedValue);
87
+		this.assertEqual('0123', value.value);
88 88
 		value = CellValue.fromCellString("'=123");
89
-		this.assertEqual(value.type, CellValue.TYPE_STRING);
90
-		this.assertEqual(value.formattedValue, '=123');
91
-		this.assertEqual(value.value, '=123');
89
+		this.assertEqual(CellValue.TYPE_STRING, value.type);
90
+		this.assertEqual('=123', value.formattedValue);
91
+		this.assertEqual('=123', value.value);
92 92
 	}
93 93
 
94 94
 	test_fromCellString_formula() {
95 95
 		var value;
96 96
 		value = CellValue.fromCellString('=A*B');
97
-		this.assertEqual(value.type, CellValue.TYPE_FORMULA);
98
-		this.assertEqual(value.formattedValue, '=A*B');
99
-		this.assertEqual(value.value, '=A*B');
97
+		this.assertEqual(CellValue.TYPE_FORMULA, value.type);
98
+		this.assertEqual('=A*B', value.formattedValue);
99
+		this.assertEqual('=A*B', value.value);
100 100
 		value = CellValue.fromCellString('=MAX(A, 3)');
101
-		this.assertEqual(value.type, CellValue.TYPE_FORMULA);
102
-		this.assertEqual(value.formattedValue, '=MAX(A, 3)');
103
-		this.assertEqual(value.value, '=MAX(A, 3)');
101
+		this.assertEqual(CellValue.TYPE_FORMULA, value.type);
102
+		this.assertEqual('=MAX(A, 3)', value.formattedValue);
103
+		this.assertEqual('=MAX(A, 3)', value.value);
104 104
 	}
105 105
 
106 106
 	test_fromValue_null() {
107 107
 		var value;
108 108
 		value = CellValue.fromValue(null);
109
-		this.assertEqual(value.type, CellValue.TYPE_BLANK);
109
+		this.assertEqual(CellValue.TYPE_BLANK, value.type);
110 110
 	}
111 111
 
112 112
 	test_fromValue_number() {
113 113
 		var value;
114 114
 		value = CellValue.fromValue(123);
115
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
116
-		this.assertEqual(value.formattedValue, '123');
115
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
116
+		this.assertEqual('123', value.formattedValue);
117 117
 		value = CellValue.fromValue(3.141592);
118
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
119
-		this.assertEqual(value.formattedValue, '3.141592');
118
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
119
+		this.assertEqual('3.141592', value.formattedValue);
120 120
 		value = CellValue.fromValue(123456789);
121
-		this.assertEqual(value.type, CellValue.TYPE_NUMBER);
122
-		this.assertEqual(value.formattedValue, '123,456,789');
121
+		this.assertEqual(CellValue.TYPE_NUMBER, value.type);
122
+		this.assertEqual('123,456,789', value.formattedValue);
123 123
 	}
124 124
 
125 125
 	test_fromValue_boolean() {
126 126
 		var value;
127 127
 		value = CellValue.fromValue(true);
128
-		this.assertEqual(value.type, CellValue.TYPE_BOOLEAN);
129
-		this.assertEqual(value.formattedValue, 'TRUE');
128
+		this.assertEqual(CellValue.TYPE_BOOLEAN, value.type);
129
+		this.assertEqual('TRUE', value.formattedValue);
130 130
 		value = CellValue.fromValue(false);
131
-		this.assertEqual(value.type, CellValue.TYPE_BOOLEAN);
132
-		this.assertEqual(value.formattedValue, 'FALSE');
131
+		this.assertEqual(CellValue.TYPE_BOOLEAN, value.type);
132
+		this.assertEqual('FALSE', value.formattedValue);
133 133
 	}
134 134
 
135 135
 	test_fromValue_string() {
136 136
 		var value;
137 137
 		value = CellValue.fromValue('foo');
138
-		this.assertEqual(value.type, CellValue.TYPE_STRING);
139
-		this.assertEqual(value.formattedValue, 'foo');
138
+		this.assertEqual(CellValue.TYPE_STRING, value.type);
139
+		this.assertEqual('foo', value.formattedValue);
140 140
 		value = CellValue.fromValue('123');
141
-		this.assertEqual(value.type, CellValue.TYPE_STRING);
142
-		this.assertEqual(value.formattedValue, '123');
141
+		this.assertEqual(CellValue.TYPE_STRING, value.type);
142
+		this.assertEqual('123', value.formattedValue);
143 143
 	}
144 144
 
145 145
 	test_fromValue_formula() {
146 146
 		var value;
147 147
 		value = CellValue.fromValue('=A*B');
148
-		this.assertEqual(value.type, CellValue.TYPE_FORMULA);
149
-		this.assertEqual(value.formattedValue, '=A*B');
148
+		this.assertEqual(CellValue.TYPE_FORMULA, value.type);
149
+		this.assertEqual('=A*B', value.formattedValue);
150 150
 	}
151 151
 
152 152
 	test_operation_add() {
153
-		var a, b, result, expected;
153
+		var a, b, expected, actual;
154 154
 		a = CellValue.fromValue(3);
155 155
 		b = CellValue.fromValue(4);
156
-		result = a.add(b)
156
+		actual = a.add(b)
157 157
 		expected = new CellValue('7', 7, CellValue.TYPE_NUMBER, 0);
158
-		this.assertEqual(result, expected);
158
+		this.assertEqual(expected, actual);
159 159
 
160 160
 		a = CellValue.fromCellString('100%');
161 161
 		b = CellValue.fromCellString('50%');
162
-		result = a.add(b);
162
+		actual = a.add(b);
163 163
 		expected = new CellValue('150%', 1.5, CellValue.TYPE_PERCENT, 0);
164
-		this.assertEqual(result, expected);
164
+		this.assertEqual(expected, actual);
165 165
 
166 166
 		a = CellValue.fromCellString('$123');
167 167
 		b = CellValue.fromCellString('$321');
168
-		result = a.add(b);
168
+		actual = a.add(b);
169 169
 		expected = new CellValue('$444.00', 444, CellValue.TYPE_CURRENCY, 2);
170
-		this.assertEqual(result, expected);
170
+		this.assertEqual(expected, actual);
171 171
 	}
172 172
 
173 173
 	test_operation_subtract() {
174
-		var a, b, result, expected;
174
+		var a, b, expected, actual;
175 175
 		a = CellValue.fromValue(9);
176 176
 		b = CellValue.fromValue(4);
177
-		result = a.subtract(b)
177
+		actual = a.subtract(b)
178 178
 		expected = new CellValue('5', 5, CellValue.TYPE_NUMBER, 0);
179
-		this.assertEqual(result, expected);
179
+		this.assertEqual(expected, actual);
180 180
 
181 181
 		a = CellValue.fromCellString('100%');
182 182
 		b = CellValue.fromCellString('50%');
183
-		result = a.subtract(b);
183
+		actual = a.subtract(b);
184 184
 		expected = new CellValue('50%', 0.5, CellValue.TYPE_PERCENT, 0);
185
-		this.assertEqual(result, expected);
185
+		this.assertEqual(expected, actual);
186 186
 
187 187
 		a = CellValue.fromCellString('$321');
188 188
 		b = CellValue.fromCellString('$123');
189
-		result = a.subtract(b);
189
+		actual = a.subtract(b);
190 190
 		expected = new CellValue('$198.00', 198, CellValue.TYPE_CURRENCY, 2);
191
-		this.assertEqual(result, expected);
191
+		this.assertEqual(expected, actual);
192 192
 	}
193 193
 
194 194
 	test_operation_multiply() {
195
-		var a, b, result, expected;
195
+		var a, b, expected, actual;
196 196
 		a = CellValue.fromValue(3);
197 197
 		b = CellValue.fromValue(4);
198
-		result = a.multiply(b)
198
+		actual = a.multiply(b)
199 199
 		expected = new CellValue('12', 12, CellValue.TYPE_NUMBER, 0);
200
-		this.assertEqual(result, expected);
200
+		this.assertEqual(expected, actual);
201 201
 
202 202
 		a = CellValue.fromCellString('150%');
203 203
 		b = CellValue.fromCellString('50%');
204
-		result = a.multiply(b);
204
+		actual = a.multiply(b);
205 205
 		expected = new CellValue('75%', 0.75, CellValue.TYPE_PERCENT, 0);
206
-		this.assertEqual(result, expected);
206
+		this.assertEqual(expected, actual);
207 207
 
208 208
 		a = CellValue.fromCellString('$321');
209 209
 		b = CellValue.fromCellString('50%');
210
-		result = a.multiply(b);
210
+		actual = a.multiply(b);
211 211
 		expected = new CellValue('$160.50', 160.50, CellValue.TYPE_CURRENCY, 2);
212
-		this.assertEqual(result, expected);
212
+		this.assertEqual(expected, actual);
213 213
 	}
214 214
 
215 215
 	test_operation_divide() {
216
-		var a, b, result, expected;
216
+		var a, b, expected, actual;
217 217
 		a = CellValue.fromValue(12);
218 218
 		b = CellValue.fromValue(4);
219
-		result = a.divide(b)
219
+		actual = a.divide(b)
220 220
 		expected = new CellValue('3', 3, CellValue.TYPE_NUMBER, 0);
221
-		this.assertEqual(result, expected);
221
+		this.assertEqual(expected, actual);
222 222
 
223 223
 		a = CellValue.fromCellString('150%');
224 224
 		b = CellValue.fromCellString('50%');
225
-		result = a.divide(b);
225
+		actual = a.divide(b);
226 226
 		expected = new CellValue('300%', 3.0, CellValue.TYPE_PERCENT, 0);
227
-		this.assertEqual(result, expected);
227
+		this.assertEqual(expected, actual);
228 228
 
229 229
 		a = CellValue.fromCellString('$321');
230 230
 		b = CellValue.fromCellString('200%');
231
-		result = a.divide(b);
231
+		actual = a.divide(b);
232 232
 		expected = new CellValue('$160.50', 160.50, CellValue.TYPE_CURRENCY, 2);
233
-		this.assertEqual(result, expected);
233
+		this.assertEqual(expected, actual);
234 234
 	}
235 235
 
236 236
 	test_operation_modulo() {
237
-		var a, b, result, expected;
237
+		var a, b, expected, actual;
238 238
 		a = CellValue.fromValue(7);
239 239
 		b = CellValue.fromValue(4);
240
-		result = a.modulo(b)
240
+		actual = a.modulo(b)
241 241
 		expected = new CellValue('3', 3, CellValue.TYPE_NUMBER, 0);
242
-		this.assertEqual(result, expected);
242
+		this.assertEqual(expected, actual);
243 243
 
244 244
 		a = CellValue.fromCellString('175%');
245 245
 		b = CellValue.fromCellString('50%');
246
-		result = a.modulo(b);
246
+		actual = a.modulo(b);
247 247
 		expected = new CellValue('25%', 0.25, CellValue.TYPE_PERCENT, 0);
248
-		this.assertEqual(result, expected);
248
+		this.assertEqual(expected, actual);
249 249
 
250 250
 		a = CellValue.fromCellString('$327');
251 251
 		b = CellValue.fromCellString('$20');
252
-		result = a.modulo(b);
252
+		actual = a.modulo(b);
253 253
 		expected = new CellValue('$7.00', 7.00, CellValue.TYPE_CURRENCY, 2);
254
-		this.assertEqual(result, expected);
254
+		this.assertEqual(expected, actual);
255 255
 	}
256 256
 
257 257
 	test_operation_unaryNot() {
258
-		this.assertEqual(CellValue.fromValue(true).not(), CellValue.fromValue(false));
259
-		this.assertEqual(CellValue.fromValue(false).not(), CellValue.fromValue(true));
258
+		this.assertEqual(CellValue.fromValue(false), CellValue.fromValue(true).not());
259
+		this.assertEqual(CellValue.fromValue(true), CellValue.fromValue(false).not());
260 260
 	}
261 261
 
262 262
 	test_operation_comparators() {
@@ -265,33 +265,33 @@ class CellValueTests extends BaseTest {
265 265
 		const t = CellValue.fromValue(true);
266 266
 		const f = CellValue.fromValue(false);
267 267
 
268
-		this.assertEqual(a.lt(b), t);
269
-		this.assertEqual(a.lte(b), t);
270
-		this.assertEqual(a.gt(b), f);
271
-		this.assertEqual(a.gte(b), f);
272
-		this.assertEqual(a.eq(b), f);
273
-		this.assertEqual(a.neq(b), t);
274
-
275
-		this.assertEqual(b.lt(a), f);
276
-		this.assertEqual(b.lte(a), f);
277
-		this.assertEqual(b.gt(a), t);
278
-		this.assertEqual(b.gte(a), t);
279
-		this.assertEqual(b.eq(a), f);
280
-		this.assertEqual(b.neq(a), t);
281
-
282
-		this.assertEqual(a.lt(a), f);
283
-		this.assertEqual(a.lte(a), t);
284
-		this.assertEqual(a.gt(a), f);
285
-		this.assertEqual(a.gte(a), t);
286
-		this.assertEqual(a.eq(a), t);
287
-		this.assertEqual(a.neq(a), f);
268
+		this.assertEqual(t, a.lt(b));
269
+		this.assertEqual(t, a.lte(b));
270
+		this.assertEqual(f, a.gt(b));
271
+		this.assertEqual(f, a.gte(b));
272
+		this.assertEqual(f, a.eq(b));
273
+		this.assertEqual(t, a.neq(b));
274
+
275
+		this.assertEqual(f, b.lt(a));
276
+		this.assertEqual(f, b.lte(a));
277
+		this.assertEqual(t, b.gt(a));
278
+		this.assertEqual(t, b.gte(a));
279
+		this.assertEqual(f, b.eq(a));
280
+		this.assertEqual(t, b.neq(a));
281
+
282
+		this.assertEqual(f, a.lt(a));
283
+		this.assertEqual(t, a.lte(a));
284
+		this.assertEqual(f, a.gt(a));
285
+		this.assertEqual(t, a.gte(a));
286
+		this.assertEqual(t, a.eq(a));
287
+		this.assertEqual(f, a.neq(a));
288 288
 	}
289 289
 
290 290
 	test_operation_concatenate() {
291 291
 		const a = CellValue.fromValue('abc');
292 292
 		const b = CellValue.fromValue('xyz');
293
-		const result = a.concatenate(b);
293
+		const actual = a.concatenate(b);
294 294
 		const expected = CellValue.fromValue('abcxyz');
295
-		this.assertEqual(result, expected);
295
+		this.assertEqual(expected, actual);
296 296
 	}
297 297
 }

+ 82
- 79
jstest/spreadsheet/ExpressionSetTests.js 查看文件

@@ -5,7 +5,8 @@ class ExpressionSetTests extends BaseTest {
5 5
 		const expressionSet = new CellExpressionSet(grid);
6 6
 		expressionSet.calculateCells();
7 7
 		const expected = CellValue.fromValue(21);
8
-		this.assertEqual(grid.cells[0][0].outputValue, expected);
8
+		const actual = grid.cells[0][0].outputValue;
9
+		this.assertEqual(expected, actual);
9 10
 	}
10 11
 
11 12
 	test_reference() {
@@ -16,7 +17,8 @@ class ExpressionSetTests extends BaseTest {
16 17
 		const expressionSet = new CellExpressionSet(grid);
17 18
 		expressionSet.calculateCells();
18 19
 		const expected = CellValue.fromValue(369);
19
-		this.assertEqual(grid.cells[2][0].outputValue, expected);
20
+		const actual = grid.cells[2][0].outputValue;
21
+		this.assertEqual(expected, actual);
20 22
 	}
21 23
 
22 24
 	test_infixPriority() {
@@ -25,7 +27,8 @@ class ExpressionSetTests extends BaseTest {
25 27
 		const expressionSet = new CellExpressionSet(grid);
26 28
 		expressionSet.calculateCells();
27 29
 		const expected = CellValue.fromValue(15);
28
-		this.assertEqual(grid.cells[0][0].outputValue, expected);
30
+		const actual = grid.cells[0][0].outputValue;
31
+		this.assertEqual(expected, actual);
29 32
 	}
30 33
 
31 34
 	test_filledFormula() {
@@ -39,9 +42,9 @@ class ExpressionSetTests extends BaseTest {
39 42
 		grid.cells[1][2].originalValue = CellValue.fromValue(9);
40 43
 		const expressionSet = new CellExpressionSet(grid);
41 44
 		expressionSet.calculateCells();
42
-		this.assertEqual(grid.cells[2][0].outputValue, CellValue.fromValue(20));
43
-		this.assertEqual(grid.cells[2][1].outputValue, CellValue.fromValue(42));
44
-		this.assertEqual(grid.cells[2][2].outputValue, CellValue.fromValue(72));
45
+		this.assertEqual(CellValue.fromValue(20), grid.cells[2][0].outputValue);
46
+		this.assertEqual(CellValue.fromValue(42), grid.cells[2][1].outputValue);
47
+		this.assertEqual(CellValue.fromValue(72), grid.cells[2][2].outputValue);
45 48
 	}
46 49
 
47 50
 	test_dependencies() {
@@ -56,157 +59,157 @@ class ExpressionSetTests extends BaseTest {
56 59
 		grid.cells[1][3].originalValue = CellValue.fromCellString('=A4');
57 60
 		const expressionSet = new CellExpressionSet(grid);
58 61
 		expressionSet.calculateCells();
59
-		this.assertEqual(grid.cells[1][0].outputValue, CellValue.fromValue(10));
60
-		this.assertEqual(grid.cells[1][1].outputValue, CellValue.fromValue(9));
61
-		this.assertEqual(grid.cells[1][2].outputValue, CellValue.fromValue(7));
62
-		this.assertEqual(grid.cells[1][3].outputValue, CellValue.fromValue(4));
62
+		this.assertEqual(CellValue.fromValue(10), grid.cells[1][0].outputValue);
63
+		this.assertEqual(CellValue.fromValue(9), grid.cells[1][1].outputValue);
64
+		this.assertEqual(CellValue.fromValue(7), grid.cells[1][2].outputValue);
65
+		this.assertEqual(CellValue.fromValue(4), grid.cells[1][3].outputValue);
63 66
 	}
64 67
 
65
-	_test_simple_formula(formula, expected) {
68
+	_test_simple_formula(expected, formula) {
66 69
 		const grid = new SpreadsheetGrid(1, 1);
67 70
 		grid.cells[0][0].originalValue = CellValue.fromCellString(formula);
68 71
 		const expressionSet = new CellExpressionSet(grid);
69 72
 		expressionSet.calculateCells();
70
-		const result = grid.cells[0][0].outputValue;
73
+		const actual = grid.cells[0][0].outputValue;
71 74
 		const exp = (expected instanceof CellValue) ? expected : CellValue.fromValue(expected);
72
-		this.assertEqual(result.type, exp.type);
73
-		this.assertEqual(result.decimals, exp.decimals);
74
-		this.assertEqual(result.formattedValue, exp.formattedValue);
75
-		this.assertEqual(result.value, exp.value);
75
+		this.assertEqual(exp.type, actual.type);
76
+		this.assertEqual(exp.decimals, actual.decimals);
77
+		this.assertEqual(exp.formattedValue, actual.formattedValue);
78
+		this.assertEqual(exp.value, actual.value);
76 79
 	}
77 80
 
78 81
 	test_func_abs() {
79
-		this._test_simple_formula('=ABS(-3)', 3);
80
-		this._test_simple_formula('=ABS(4)', 4);
82
+		this._test_simple_formula(3, '=ABS(-3)');
83
+		this._test_simple_formula(4, '=ABS(4)');
81 84
 	}
82 85
 
83 86
 	test_func_and() {
84
-		this._test_simple_formula('=AND(FALSE, FALSE)', false);
85
-		this._test_simple_formula('=AND(FALSE, TRUE)', false);
86
-		this._test_simple_formula('=AND(TRUE, FALSE)', false);
87
-		this._test_simple_formula('=AND(TRUE, TRUE)', true);
88
-		this._test_simple_formula('=AND(TRUE, TRUE, TRUE, TRUE)', true);
89
-		this._test_simple_formula('=AND(TRUE, TRUE, TRUE, FALSE)', false);
87
+		this._test_simple_formula(false, '=AND(FALSE, FALSE)');
88
+		this._test_simple_formula(false, '=AND(FALSE, TRUE)');
89
+		this._test_simple_formula(false, '=AND(TRUE, FALSE)');
90
+		this._test_simple_formula(true, '=AND(TRUE, TRUE)');
91
+		this._test_simple_formula(true, '=AND(TRUE, TRUE, TRUE, TRUE)');
92
+		this._test_simple_formula(false, '=AND(TRUE, TRUE, TRUE, FALSE)');
90 93
 	}
91 94
 
92 95
 	test_func_average() {
93
-		this._test_simple_formula('=AVERAGE(4, 6, 2, 4)', 4);
94
-		this._test_simple_formula('=AVERAGE(4, 6, 2, "foo", 4)', 4);
96
+		this._test_simple_formula(4, '=AVERAGE(4, 6, 2, 4)');
97
+		this._test_simple_formula(4, '=AVERAGE(4, 6, 2, "foo", 4)');
95 98
 	}
96 99
 
97 100
 	test_func_ceiling() {
98
-		this._test_simple_formula('=CEILING(3.1)', 4);
99
-		this._test_simple_formula('=CEILING(3)', 3);
100
-		this._test_simple_formula('=CEILING(-3.1)', -3);
101
+		this._test_simple_formula(4, '=CEILING(3.1)');
102
+		this._test_simple_formula(3, '=CEILING(3)');
103
+		this._test_simple_formula(-3, '=CEILING(-3.1)');
101 104
 	}
102 105
 
103 106
 	test_func_exp() {
104
-		this._test_simple_formula('=EXP(1)', 2.718281828459045);
107
+		this._test_simple_formula(2.718281828459045, '=EXP(1)');
105 108
 	}
106 109
 
107 110
 	test_func_floor() {
108
-		this._test_simple_formula('=FLOOR(3.1)', 3);
109
-		this._test_simple_formula('=FLOOR(3)', 3);
110
-		this._test_simple_formula('=FLOOR(-3.1)', -4);
111
+		this._test_simple_formula(3, '=FLOOR(3.1)');
112
+		this._test_simple_formula(3, '=FLOOR(3)');
113
+		this._test_simple_formula(-4, '=FLOOR(-3.1)');
111 114
 	}
112 115
 
113 116
 	test_func_if() {
114
-		this._test_simple_formula('=IF(FALSE, 4, 6)', 6);
115
-		this._test_simple_formula('=IF(TRUE, 4, 6)', 4);
117
+		this._test_simple_formula(6, '=IF(FALSE, 4, 6)');
118
+		this._test_simple_formula(4, '=IF(TRUE, 4, 6)');
116 119
 	}
117 120
 
118 121
 	test_func_ifs() {
119
-		this._test_simple_formula('=IFS(TRUE, 1, FALSE, 2, FALSE, 3, FALSE, 4, 5)', 1);
120
-		this._test_simple_formula('=IFS(FALSE, 1, TRUE, 2, FALSE, 3, FALSE, 4, 5)', 2);
121
-		this._test_simple_formula('=IFS(FALSE, 1, FALSE, 2, TRUE, 3, FALSE, 4, 5)', 3);
122
-		this._test_simple_formula('=IFS(FALSE, 1, FALSE, 2, FALSE, 3, TRUE, 4, 5)', 4);
123
-		this._test_simple_formula('=IFS(FALSE, 1, FALSE, 2, FALSE, 3, FALSE, 4, 5)', 5);
122
+		this._test_simple_formula(1, '=IFS(TRUE, 1, FALSE, 2, FALSE, 3, FALSE, 4, 5)');
123
+		this._test_simple_formula(2, '=IFS(FALSE, 1, TRUE, 2, FALSE, 3, FALSE, 4, 5)');
124
+		this._test_simple_formula(3, '=IFS(FALSE, 1, FALSE, 2, TRUE, 3, FALSE, 4, 5)');
125
+		this._test_simple_formula(4, '=IFS(FALSE, 1, FALSE, 2, FALSE, 3, TRUE, 4, 5)');
126
+		this._test_simple_formula(5, '=IFS(FALSE, 1, FALSE, 2, FALSE, 3, FALSE, 4, 5)');
124 127
 	}
125 128
 
126 129
 	test_func_ln() {
127
-		this._test_simple_formula('=LN(2.718281828459045)', 1);
130
+		this._test_simple_formula(1, '=LN(2.718281828459045)');
128 131
 	}
129 132
 
130 133
 	test_func_log() {
131
-		this._test_simple_formula('=LOG(1000, 10)', 3);
132
-		this._test_simple_formula('=LOG(64, 2)', 6);
134
+		this._test_simple_formula(3, '=LOG(1000, 10)');
135
+		this._test_simple_formula(6, '=LOG(64, 2)');
133 136
 	}
134 137
 
135 138
 	test_func_lower() {
136
-		this._test_simple_formula('=LOWER("MiXeD")', 'mixed');
139
+		this._test_simple_formula('mixed', '=LOWER("MiXeD")');
137 140
 	}
138 141
 
139 142
 	test_func_max() {
140
-		this._test_simple_formula('=MAX(4, 8, 5, 2)', 8);
143
+		this._test_simple_formula(8, '=MAX(4, 8, 5, 2)');
141 144
 	}
142 145
 
143 146
 	test_func_min() {
144
-		this._test_simple_formula('=MIN(4, 8, 5, 2)', 2);
147
+		this._test_simple_formula(2, '=MIN(4, 8, 5, 2)');
145 148
 	}
146 149
 
147 150
 	test_func_mod() {
148
-		this._test_simple_formula('=MOD(37, 4)', 1);
151
+		this._test_simple_formula(1, '=MOD(37, 4)');
149 152
 	}
150 153
 
151 154
 	test_func_not() {
152
-		this._test_simple_formula('=NOT(TRUE)', false);
153
-		this._test_simple_formula('=NOT(FALSE)', true);
155
+		this._test_simple_formula(false, '=NOT(TRUE)');
156
+		this._test_simple_formula(true, '=NOT(FALSE)');
154 157
 	}
155 158
 
156 159
 	test_func_or() {
157
-		this._test_simple_formula('=OR(FALSE, FALSE)', false);
158
-		this._test_simple_formula('=OR(FALSE, TRUE)', true);
159
-		this._test_simple_formula('=OR(TRUE, FALSE)', true);
160
-		this._test_simple_formula('=OR(TRUE, TRUE)', true);
161
-		this._test_simple_formula('=OR(FALSE, FALSE, FALSE, TRUE)', true);
160
+		this._test_simple_formula(false, '=OR(FALSE, FALSE)');
161
+		this._test_simple_formula(true, '=OR(FALSE, TRUE)');
162
+		this._test_simple_formula(true, '=OR(TRUE, FALSE)');
163
+		this._test_simple_formula(true, '=OR(TRUE, TRUE)');
164
+		this._test_simple_formula(true, '=OR(FALSE, FALSE, FALSE, TRUE)');
162 165
 	}
163 166
 
164 167
 	test_func_power() {
165
-		this._test_simple_formula('=POWER(2, 3)', 8);
168
+		this._test_simple_formula(8, '=POWER(2, 3)');
166 169
 	}
167 170
 
168 171
 	test_func_round() {
169
-		this._test_simple_formula('=ROUND(3.1)', 3);
170
-		this._test_simple_formula('=ROUND(3.5)', 4);
171
-		this._test_simple_formula('=ROUND(4)', 4);
172
-		this._test_simple_formula('=ROUND(-3.1)', -3);
173
-		this._test_simple_formula('=ROUND(-3.5)', -3);
174
-		this._test_simple_formula('=ROUND(-3.9)', -4);
175
-		this._test_simple_formula('=ROUND(3.1415926535, 1)', 3.1);
176
-		this._test_simple_formula('=ROUND(3.1415926535, 2)', 3.14);
177
-		this._test_simple_formula('=ROUND(31.415926535, -1)', 30);
172
+		this._test_simple_formula(3, '=ROUND(3.1)');
173
+		this._test_simple_formula(4, '=ROUND(3.5)');
174
+		this._test_simple_formula(4, '=ROUND(4)');
175
+		this._test_simple_formula(-3, '=ROUND(-3.1)');
176
+		this._test_simple_formula(-3, '=ROUND(-3.5)');
177
+		this._test_simple_formula(-4, '=ROUND(-3.9)');
178
+		this._test_simple_formula(3.1, '=ROUND(3.1415926535, 1)');
179
+		this._test_simple_formula(3.14, '=ROUND(3.1415926535, 2)');
180
+		this._test_simple_formula(30, '=ROUND(31.415926535, -1)');
178 181
 	}
179 182
 
180 183
 	test_func_sqrt() {
181
-		this._test_simple_formula('=SQRT(16)', 4);
184
+		this._test_simple_formula(4, '=SQRT(16)');
182 185
 	}
183 186
 
184 187
 	test_func_substitute() {
185
-		this._test_simple_formula('=SUBSTITUTE("cat sat on the mat", "at", "ot")', 'cot sot on the mot');
186
-		this._test_simple_formula('=SUBSTITUTE("cAt saT on the mat", "at", "ot")', 'cot sot on the mot');
187
-		this._test_simple_formula('=SUBSTITUTE("c.*t s.*t on the m.*t", ".*t", "ot")', 'cot sot on the mot');
188
+		this._test_simple_formula('cot sot on the mot', '=SUBSTITUTE("cat sat on the mat", "at", "ot")');
189
+		this._test_simple_formula('cot sot on the mot', '=SUBSTITUTE("cAt saT on the mat", "at", "ot")');
190
+		this._test_simple_formula('cot sot on the mot', '=SUBSTITUTE("c.*t s.*t on the m.*t", ".*t", "ot")');
188 191
 	}
189 192
 
190 193
 	test_func_sum() {
191
-		this._test_simple_formula('=SUM(1, 2, 3, 4, 5)', 15);
194
+		this._test_simple_formula(15, '=SUM(1, 2, 3, 4, 5)');
192 195
 	}
193 196
 
194 197
 	test_func_upper() {
195
-		this._test_simple_formula('=UPPER("mIxEd")', 'MIXED');
198
+		this._test_simple_formula('MIXED', '=UPPER("mIxEd")');
196 199
 	}
197 200
 
198 201
 	test_func_xor() {
199
-		this._test_simple_formula('=XOR(FALSE, FALSE)', false);
200
-		this._test_simple_formula('=XOR(FALSE, TRUE)', true);
201
-		this._test_simple_formula('=XOR(TRUE, FALSE)', true);
202
-		this._test_simple_formula('=XOR(TRUE, TRUE)', false);
203
-		this._test_simple_formula('=XOR(FALSE, FALSE, TRUE)', true);
204
-		this._test_simple_formula('=XOR(TRUE, FALSE, TRUE)', false);
202
+		this._test_simple_formula(false, '=XOR(FALSE, FALSE)');
203
+		this._test_simple_formula(true, '=XOR(FALSE, TRUE)');
204
+		this._test_simple_formula(true, '=XOR(TRUE, FALSE)');
205
+		this._test_simple_formula(false, '=XOR(TRUE, TRUE)');
206
+		this._test_simple_formula(true, '=XOR(FALSE, FALSE, TRUE)');
207
+		this._test_simple_formula(false, '=XOR(TRUE, FALSE, TRUE)');
205 208
 	}
206 209
 
207 210
 	test_format() {
208
-		this._test_simple_formula('=2.718281828459045 ; number 3', new CellValue('2.718', 2.718281828459045, 'number', 3));
209
-		this._test_simple_formula('=2.718281828459045 ; percent 2', new CellValue('271.83%', 2.718281828459045, 'percent', 2));
210
-		this._test_simple_formula('=2.718281828459045 ; currency 2', new CellValue('$2.72', 2.718281828459045, 'currency', 2));
211
+		this._test_simple_formula(new CellValue('2.718', 2.718281828459045, 'number', 3), '=2.718281828459045 ; number 3');
212
+		this._test_simple_formula(new CellValue('271.83%', 2.718281828459045, 'percent', 2), '=2.718281828459045 ; percent 2');
213
+		this._test_simple_formula(new CellValue('$2.72', 2.718281828459045, 'currency', 2), '=2.718281828459045 ; currency 2');
211 214
 	}
212 215
 }

+ 37
- 37
jstest/spreadsheet/SpreadsheetMarkdownIntegrationTests.js 查看文件

@@ -11,52 +11,52 @@ class SpreadsheetMarkdownIntegrationTests extends BaseTest {
11 11
 
12 12
 	test_integration() {
13 13
 		const markdown = '| A | B | C |\n| --- | --- | --- |\n| 3 | 4 | =A*B |';
14
-		const expected = '<table> <thead> ' +
15
-			'<tr> <th>A</th> <th>B</th> <th>C</th> </tr> ' +
16
-			'</thead> <tbody> <tr> ' +
17
-			'<td class="spreadsheet-type-number" data-numeric-value="3" data-string-value="3">3</td> ' +
18
-			'<td class="spreadsheet-type-number" data-numeric-value="4" data-string-value="4">4</td> ' +
19
-			'<td class="calculated spreadsheet-type-number" data-numeric-value="12" data-string-value="12">12</td> ' +
20
-			'</tr> </tbody> </table>';
21
-		const result = this.md(markdown);
22
-		this.assertEqual(result, expected);
14
+		const expected = '<table><thead>' +
15
+			'<tr><th>A</th><th>B</th><th>C</th></tr>' +
16
+			'</thead><tbody><tr>' +
17
+			'<td class="spreadsheet-type-number" data-numeric-value="3" data-string-value="3">3</td>' +
18
+			'<td class="spreadsheet-type-number" data-numeric-value="4" data-string-value="4">4</td>' +
19
+			'<td class="calculated spreadsheet-type-number" data-numeric-value="12" data-string-value="12">12</td>' +
20
+			'</tr></tbody></table>';
21
+		const actual = this.md(markdown);
22
+		this.assertEqual(expected, actual);
23 23
 	}
24 24
 
25 25
 	test_bailOut() {
26 26
 		// If no formulas found table isn't modified
27 27
 		const markdown = '| A | B | C |\n| --- | --- | --- |\n| 3 | 4 | A*B |';
28
-		const expected = '<table> <thead> ' +
29
-			'<tr> <th>A</th> <th>B</th> <th>C</th> </tr> ' +
30
-			'</thead> <tbody> <tr> ' +
31
-			'<td>3</td> ' +
32
-			'<td>4</td> ' +
33
-			'<td>A*B</td> ' +
34
-			'</tr> </tbody> </table>';
35
-		const result = this.md(markdown);
36
-		this.assertEqual(result, expected);
28
+		const expected = '<table><thead>' +
29
+			'<tr><th>A</th><th>B</th><th>C</th></tr>' +
30
+			'</thead><tbody><tr>' +
31
+			'<td>3</td>' +
32
+			'<td>4</td>' +
33
+			'<td>A*B</td>' +
34
+			'</tr></tbody></table>';
35
+		const actual = this.md(markdown);
36
+		this.assertEqual(expected, actual);
37 37
 	}
38 38
 
39 39
 	test_observedError1() {
40 40
 		// Saw "Uncaught Error: columnIndex must be number, got string" from this
41 41
 		const markdown = '| Unit Price | Qty | Subtotal |\n| ---: | ---: | ---: |\n| $1.23 | 2 | =A*B FILL |\n| $4.99 | 6 | |\n| Total | | =SUM(C:C) |';
42
-		const expected = '<table> <thead> <tr> ' +
43
-			'<th style="text-align: right;">Unit Price</th> ' +
44
-			'<th style="text-align: right;">Qty</th> ' +
45
-			'<th>Subtotal</th> ' +
46
-			'</tr> </thead> <tbody> <tr> ' +
47
-			'<td class="spreadsheet-type-currency" style="text-align: right;" data-numeric-value="1.23" data-string-value="1.23">$1.23</td> ' +
48
-			'<td class="spreadsheet-type-number" style="text-align: right;" data-numeric-value="2" data-string-value="2">2</td> ' +
49
-			'<td class="calculated spreadsheet-type-currency" data-numeric-value="2.46" data-string-value="2.46">$2.46</td> ' +
50
-			'</tr> <tr> ' +
51
-			'<td class="spreadsheet-type-currency" style="text-align: right;" data-numeric-value="4.99" data-string-value="4.99">$4.99</td> ' +
52
-			'<td class="spreadsheet-type-number" style="text-align: right;" data-numeric-value="6" data-string-value="6">6</td> ' +
53
-			'<td class="calculated spreadsheet-type-currency" data-numeric-value="29.94" data-string-value="29.94">$29.94</td> ' +
54
-			'</tr> <tr> ' +
55
-			'<td class="spreadsheet-type-string" style="text-align: right;" data-string-value="Total">Total</td> ' +
56
-			'<td class="spreadsheet-type-blank" style="text-align: right;" data-numeric-value="0" data-string-value=""></td> ' +
57
-			'<td class="calculated spreadsheet-type-currency" data-numeric-value="32.4" data-string-value="32.4">$32.40</td> ' +
58
-			'</tr> </tbody> </table>';
59
-		const result = this.md(markdown);
60
-		this.assertEqual(result, expected);
42
+		const expected = '<table><thead><tr>' +
43
+			'<th style="text-align: right;">Unit Price</th>' +
44
+			'<th style="text-align: right;">Qty</th>' +
45
+			'<th>Subtotal</th>' +
46
+			'</tr></thead><tbody><tr>' +
47
+			'<td class="spreadsheet-type-currency" style="text-align: right;" data-numeric-value="1.23" data-string-value="1.23">$1.23</td>' +
48
+			'<td class="spreadsheet-type-number" style="text-align: right;" data-numeric-value="2" data-string-value="2">2</td>' +
49
+			'<td class="calculated spreadsheet-type-currency" data-numeric-value="2.46" data-string-value="2.46">$2.46</td>' +
50
+			'</tr><tr>' +
51
+			'<td class="spreadsheet-type-currency" style="text-align: right;" data-numeric-value="4.99" data-string-value="4.99">$4.99</td>' +
52
+			'<td class="spreadsheet-type-number" style="text-align: right;" data-numeric-value="6" data-string-value="6">6</td>' +
53
+			'<td class="calculated spreadsheet-type-currency" data-numeric-value="29.94" data-string-value="29.94">$29.94</td>' +
54
+			'</tr><tr>' +
55
+			'<td class="spreadsheet-type-string" style="text-align: right;" data-string-value="Total">Total</td>' +
56
+			'<td class="spreadsheet-type-blank" style="text-align: right;" data-numeric-value="0" data-string-value=""></td>' +
57
+			'<td class="calculated spreadsheet-type-currency" data-numeric-value="32.4" data-string-value="32.4">$32.40</td>' +
58
+			'</tr></tbody></table>';
59
+		const actual = this.md(markdown);
60
+		this.assertEqual(expected, actual);
61 61
 	}
62 62
 }

+ 11
- 15
php/markdown.php 查看文件

@@ -1915,19 +1915,18 @@ class _MDListReader extends MDReader {
1915 1915
 		return MDUtils::stripIndent($lines);
1916 1916
 	}
1917 1917
 
1918
-	protected function readListItemContent(MDState $state, int $firstLineStartPos): MDBlockNode {
1918
+	protected function readListItemContent(MDState $state, int $firstLineStartPos): MDNode|array {
1919 1919
 		$itemLines = $this->readItemLines($state, $firstLineStartPos);
1920 1920
 		$state->p += max(sizeof($itemLines), 1);
1921 1921
 
1922 1922
 		if (sizeof($itemLines) == 1) {
1923
-			return new MDBlockNode($state->inlineMarkdownToNodes($itemLines[0]));
1923
+			return $state->inlineMarkdownToNodes($itemLines[0]);
1924 1924
 		}
1925 1925
 
1926 1926
 		$hasBlankLines = sizeof(array_filter($itemLines, fn($line) => trim($line) == '')) > 0;
1927 1927
 		if ($hasBlankLines) {
1928 1928
 			$substate = $state->copy($itemLines);
1929
-			$blocks = $substate->readBlocks();
1930
-			return (sizeof($blocks) == 1) ? $blocks[0] : new MBlockDNode($blocks);
1929
+			return $substate->readBlocks();
1931 1930
 		}
1932 1931
 
1933 1932
 		// Multiline content with no blank lines. Search for new block
@@ -1936,19 +1935,18 @@ class _MDListReader extends MDReader {
1936 1935
 			$line = $itemLines[$p];
1937 1936
 			if (mb_eregi('^(?:\\*|\\-|\\+|\\d+\\.)\\s+', $line)) {
1938 1937
 				// Nested list found
1939
-				$firstBlock = new MDBlockNode($state->inlineMarkdownToNodes(
1940
-					implode("\n", array_slice($itemLines, 0, $p))));
1938
+				$firstNodes = $state->inlineMarkdownToNodes(
1939
+					implode("\n", array_slice($itemLines, 0, $p)));
1941 1940
 				$substate = $state->copy(array_slice($itemLines, $p));
1942 1941
 				$blocks = $substate->readBlocks();
1943
-				return new MDBlockNode(array_merge([ $firstBlock ], $blocks));
1942
+				return new MDBlockNode(array_merge($firstNodes, $blocks));
1944 1943
 			}
1945 1944
 		}
1946 1945
 
1947 1946
 		// Ok, give up and just do a standard block read
1948 1947
 		{
1949 1948
 			$substate = $state->copy($itemLines);
1950
-			$blocks = $substate->readBlocks();
1951
-			return (sizeof($blocks) == 1) ? $blocks[0] : new MDBlockNode($blocks);
1949
+			return $substate->readBlocks();
1952 1950
 		}
1953 1951
 	}
1954 1952
 
@@ -2030,7 +2028,7 @@ class MDFencedCodeBlockReader extends MDReader {
2030 2028
 		$openFenceLine = $state->lines[$p++];
2031 2029
 		[$openFenceLine, $modifier] = MDTagModifier::fromLine($openFenceLine, $state);
2032 2030
 		if (!mb_eregi('```\\s*([a-z0-9]*)\\s*$', $openFenceLine, $groups)) return null;
2033
-		$language = mb_strlen($groups[1]) > 0 ? $groups[1] : null;
2031
+		$language = $groups[1] !== false && mb_strlen($groups[1]) > 0 ? $groups[1] : null;
2034 2032
 		$codeLines = [];
2035 2033
 		while ($state->hasLines(1, $p)) {
2036 2034
 			$line = $state->lines[$p++];
@@ -3156,8 +3154,8 @@ class MDNode {
3156 3154
 	 * and child content will be rendered between the tags.
3157 3155
 	 */
3158 3156
 	protected function simplePairedTagHTML(MDState $state, string $tagName): string {
3159
-		$openTagSuffix = $this->children[0] instanceof MDBlockNode ? "\n" : "";
3160
-		$closeTagPrefix = $this->children[sizeof($this->children) - 1] instanceof MDBlockNode ? "\n" : '';
3157
+		$openTagSuffix = ($this->children[0] ?? null) instanceof MDBlockNode ? "\n" : "";
3158
+		$closeTagPrefix = ($this->children[sizeof($this->children) - 1] ?? null) instanceof MDBlockNode ? "\n" : '';
3161 3159
 		$closeTagSuffix = $this instanceof MDBlockNode ? "\n" : '';
3162 3160
 		$attr = $this->htmlAttributes();
3163 3161
 		$childHTML = $this->childHTML($state);
@@ -3183,9 +3181,7 @@ class MDNode {
3183 3181
 	 * @return string HTML string
3184 3182
 	 */
3185 3183
 	public static function arrayToHTML(array $nodes, MDState $state): string {
3186
-		return implode('', array_map(function($node) use ($state) {
3187
-			return $node->toHTML($state) . ($node instanceof MDBlockNode ? "\n" : '');
3188
-		}, $nodes));
3184
+		return implode('', array_map(fn($node) => $node->toHTML($state) . ($node instanceof MDBlockNode ? "\n" : ''), $nodes));
3189 3185
 	}
3190 3186
 
3191 3187
 	/**

+ 290
- 0
phptest/BlockTests.php 查看文件

@@ -0,0 +1,290 @@
1
+<?php
2
+declare(strict_types=1);
3
+
4
+use PHPUnit\Framework\TestCase;
5
+
6
+require_once __DIR__ . '/../php/markdown.php';
7
+
8
+final class BlockTests extends TestCase {
9
+	private ?Markdown $parser = null;
10
+
11
+	protected function setUp(): void {
12
+		parent::setUp();
13
+		$this->parser = Markdown::completeParser();
14
+	}
15
+
16
+	private function md(string $markdown): string {
17
+		return $this->normalizeWhitespace($this->parser->toHTML($markdown));
18
+	}
19
+
20
+	private function normalizeWhitespace(string $str): string {
21
+		$str = mb_eregi_replace('\\s+', ' ', $str);
22
+		$str = mb_eregi_replace('>\\s+<', '><', $str);
23
+		return trim($str);
24
+	}
25
+
26
+	public function test_paragraphs() {
27
+		$markdown = "Lorem ipsum\n\nDolor sit amet";
28
+		$expected = "<p>Lorem ipsum</p><p>Dolor sit amet</p>";
29
+		$actual = $this->md($markdown);
30
+		$this->assertSame($expected, $actual);
31
+	}
32
+
33
+	public function test_paragraph_lineGrouping() {
34
+		$markdown = "Lorem ipsum\ndolor sit amet";
35
+		$expected = "Lorem ipsum dolor sit amet";
36
+		$actual = $this->md($markdown);
37
+		$this->assertSame($expected, $actual);
38
+	}
39
+
40
+	public function test_header_underlineH1() {
41
+		$markdown = "Header 1\n===\n\nLorem ipsum";
42
+		$expected = "<h1>Header 1</h1><p>Lorem ipsum</p>";
43
+		$actual = $this->md($markdown);
44
+		$this->assertSame($expected, $actual);
45
+	}
46
+
47
+	public function test_header_underlineH2() {
48
+		$markdown = "Header 2\n---\n\nLorem ipsum";
49
+		$expected = "<h2>Header 2</h2><p>Lorem ipsum</p>";
50
+		$actual = $this->md($markdown);
51
+		$this->assertSame($expected, $actual);
52
+	}
53
+
54
+	public function test_header_hash() {
55
+		$markdown = "# Header 1\n## Header 2\n### Header 3\n#### Header 4\n##### Header 5\n###### Header 6\n";
56
+		$expected = '<h1>Header 1</h1><h2>Header 2</h2><h3>Header 3</h3><h4>Header 4</h4><h5>Header 5</h5><h6>Header 6</h6>';
57
+		$actual = $this->md($markdown);
58
+		$this->assertSame($expected, $actual);
59
+	}
60
+
61
+	public function test_header_hash_trailing() {
62
+		$markdown = "# Header 1 #\n## Header 2 ##\n### Header 3 ######";
63
+		$expected = '<h1>Header 1</h1><h2>Header 2</h2><h3>Header 3</h3>';
64
+		$actual = $this->md($markdown);
65
+		$this->assertSame($expected, $actual);
66
+	}
67
+
68
+	public function test_unorderedList() {
69
+		$markdown = "* Lorem\n* Ipsum\n* Dolor";
70
+		$expected = '<ul><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ul>';
71
+		$actual = $this->md($markdown);
72
+		$this->assertSame($expected, $actual);
73
+	}
74
+
75
+	public function test_unorderedList_nested() {
76
+		$markdown = "* Lorem\n + Ipsum\n* Dolor";
77
+		$expected = '<ul><li> Lorem<ul><li>Ipsum</li></ul></li><li>Dolor</li></ul>';
78
+		$actual = $this->md($markdown);
79
+		$this->assertSame($expected, $actual);
80
+	}
81
+
82
+	public function test_unorderedList_hitch() {
83
+		// This incomplete bulleted list locked up the browser at one
84
+		// point, not forever but a REALLY long time
85
+		$markdown = "Testing\n\n* ";
86
+		$expected = '<p>Testing</p><ul><li></li></ul>';
87
+		$actual = $this->md($markdown);
88
+		$this->assertSame($expected, $actual);
89
+	}
90
+
91
+	public function test_orderedList() {
92
+		$markdown = "1. Lorem\n1. Ipsum\n5. Dolor";
93
+		$expected = '<ol><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ol>';
94
+		$actual = $this->md($markdown);
95
+		$this->assertSame($expected, $actual);
96
+	}
97
+
98
+	public function test_orderedList_numbering() {
99
+		$markdown = "4. Lorem\n1. Ipsum\n9. Dolor";
100
+		$expected = '<ol start="4"><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ol>';
101
+		$actual = $this->md($markdown);
102
+		$this->assertSame($expected, $actual);
103
+	}
104
+
105
+	public function test_orderedList_nested1() {
106
+		$markdown = "1. Lorem\n 1. Ipsum\n1. Dolor";
107
+		$expected = '<ol><li> Lorem<ol><li>Ipsum</li></ol></li><li>Dolor</li></ol>';
108
+		$actual = $this->md($markdown);
109
+		$this->assertSame($expected, $actual);
110
+	}
111
+
112
+	public function test_orderedList_nested2() {
113
+		$markdown = "1. Lorem\n 1. Ipsum\n      1. Dolor\n 1. Sit\n1. Amet";
114
+		$expected = '<ol><li> Lorem<ol><li> Ipsum<ol><li>Dolor</li></ol></li><li>Sit</li></ol></li><li>Amet</li></ol>';
115
+		$actual = $this->md($markdown);
116
+		$this->assertSame($expected, $actual);
117
+	}
118
+
119
+	public function test_blockquote() {
120
+		$markdown = '> Lorem ipsum dolor';
121
+		$expected = '<blockquote> Lorem ipsum dolor </blockquote>';
122
+		$actual = $this->md($markdown);
123
+		$this->assertSame($expected, $actual);
124
+	}
125
+
126
+	public function test_blockquote_paragraphs() {
127
+		$markdown = "> Lorem ipsum dolor\n>\n>Sit amet";
128
+		$expected = '<blockquote><p>Lorem ipsum dolor</p><p>Sit amet</p></blockquote>';
129
+		$actual = $this->md($markdown);
130
+		$this->assertSame($expected, $actual);
131
+	}
132
+
133
+	public function test_blockquote_list() {
134
+		$markdown = "> 1. Lorem\n> 2. Ipsum";
135
+		$expected = '<blockquote><ol><li>Lorem</li><li>Ipsum</li></ol></blockquote>';
136
+		$actual = $this->md($markdown);
137
+		$this->assertSame($expected, $actual);
138
+	}
139
+
140
+	public function test_codeBlock_indented() {
141
+		$markdown = "Code\n\n    function foo() {\n        return 'bar';\n    }\n\nend";
142
+		$expected = "<p>Code</p>\n\n<pre><code>function foo() {\n    return 'bar';\n}</code></pre>\n\n<p>end</p>";
143
+		$actual = trim($this->parser->toHTML($markdown)); // don't normalize whitespace
144
+		$this->assertSame(mb_ereg_replace(' ', '⎵', $expected), mb_ereg_replace(' ', '⎵', $actual));
145
+	}
146
+
147
+	public function test_codeBlock_fenced() {
148
+		$markdown = "Code\n\n```\nfunction foo() {\n    return 'bar';\n}\n```\n\nend";
149
+		$expected = "<p>Code</p>\n\n<pre><code>function foo() {\n    return 'bar';\n}</code></pre>\n\n<p>end</p>";
150
+		$actual = trim($this->parser->toHTML($markdown)); // don't normalize whitespace
151
+		$this->assertSame(mb_ereg_replace(' ', '⎵', $expected), mb_ereg_replace(' ', '⎵', $actual));
152
+	}
153
+
154
+	public function test_codeBlock_fenced_language() {
155
+		$markdown = "Code\n\n```javascript\nfunction foo() {\n    return 'bar';\n}\n```\n\nend";
156
+		$expected = "<p>Code</p>\n\n<pre><code class=\"language-javascript\">function foo() {\n    return 'bar';\n}</code></pre>\n\n<p>end</p>";
157
+		$actual = trim($this->parser->toHTML($markdown)); // don't normalize whitespace
158
+		$this->assertSame(mb_ereg_replace(' ', '⎵', $expected), mb_ereg_replace(' ', '⎵', $actual));
159
+	}
160
+
161
+	public function test_horizontalRule() {
162
+		$markdown = "Before\n\n---\n\n- - -\n\n***\n\n* * * * * * *\n\nafter";
163
+		$expected = "<p>Before</p><hr><hr><hr><hr><p>after</p>";
164
+		$actual = $this->md($markdown);
165
+		$this->assertSame($expected, $actual);
166
+	}
167
+
168
+	public function test_table_unfenced() {
169
+		$markdown = "Column A | Column B | Column C\n--- | --- | ---\n1 | 2 | 3\n4 | 5 | 6";
170
+		$expected = "<table><thead><tr><th>Column A</th><th>Column B</th><th>Column C</th></tr></thead><tbody><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr></tbody></table>";
171
+		$actual = $this->md($markdown);
172
+		$this->assertSame($expected, $actual);
173
+	}
174
+
175
+	public function test_table_fenced() {
176
+		$markdown = "| Column A | Column B | Column C |\n| --- | --- | --- |\n| 1 | 2 | 3\n4 | 5 | 6 |";
177
+		$expected = "<table><thead><tr><th>Column A</th><th>Column B</th><th>Column C</th></tr></thead><tbody><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr></tbody></table>";
178
+		$actual = $this->md($markdown);
179
+		$this->assertSame($expected, $actual);
180
+	}
181
+
182
+	public function test_table_alignment() {
183
+		$markdown = "Column A | Column B | Column C\n" .
184
+			":--- | :---: | ---:\n" .
185
+			"1 | 2 | 3\n" .
186
+			"4 | 5 | 6";
187
+		$expected = '<table>' .
188
+			'<thead>' .
189
+			'<tr>' .
190
+			'<th style="text-align: left;">Column A</th>' .
191
+			'<th style="text-align: center;">Column B</th>' .
192
+			'<th style="text-align: right;">Column C</th>' .
193
+			'</tr>' .
194
+			'</thead>' .
195
+			'<tbody>' .
196
+			'<tr>' .
197
+			'<td style="text-align: left;">1</td>' .
198
+			'<td style="text-align: center;">2</td>' .
199
+			'<td style="text-align: right;">3</td>' .
200
+			'</tr>' .
201
+			'<tr>' .
202
+			'<td style="text-align: left;">4</td>' .
203
+			'<td style="text-align: center;">5</td>' .
204
+			'<td style="text-align: right;">6</td>' .
205
+			'</tr>' .
206
+			'</tbody>' .
207
+			'</table>';
208
+		$actual = $this->md($markdown);
209
+		$this->assertSame($expected, $actual);
210
+	}
211
+
212
+	public function test_table_holes() {
213
+		$markdown = "Column A||Column C\n" .
214
+			"---|---|---\n" .
215
+			"|1|2||\n" .
216
+			"|4||6|\n" .
217
+			"||8|9|";
218
+		$expected = '<table>' .
219
+			'<thead>' .
220
+			'<tr>' .
221
+			'<th>Column A</th>' .
222
+			'<th></th>' .
223
+			'<th>Column C</th>' .
224
+			'</tr>' .
225
+			'</thead>' .
226
+			'<tbody>' .
227
+			'<tr>' .
228
+			'<td>1</td>' .
229
+			'<td>2</td>' .
230
+			'<td></td>' .
231
+			'</tr>' .
232
+			'<tr>' .
233
+			'<td>4</td>' .
234
+			'<td></td>' .
235
+			'<td>6</td>' .
236
+			'</tr>' .
237
+			'<tr>' .
238
+			'<td></td>' .
239
+			'<td>8</td>' .
240
+			'<td>9</td>' .
241
+			'</tr>' .
242
+			'</tbody>' .
243
+			'</table>';
244
+		$actual = $this->md($markdown);
245
+		$this->assertSame($expected, $actual);
246
+	}
247
+
248
+	public function test_definitionList() {
249
+		$markdown = "term\n" .
250
+			": definition\n" .
251
+			"another" .
252
+			" term\n" .
253
+			": def 1\n" .
254
+			" broken on next line\n" .
255
+			": def 2";
256
+		$expected = '<dl>' .
257
+			'<dt>term</dt>' .
258
+			'<dd>definition</dd>' .
259
+			'<dt>another term</dt>' .
260
+			'<dd>def 1 broken on next line</dd>' .
261
+			'<dd>def 2</dd>' .
262
+			'</dl>';
263
+		$actual = $this->md($markdown);
264
+		$this->assertSame($expected, $actual);
265
+	}
266
+
267
+	public function test_footnotes() {
268
+		$markdown = "Lorem ipsum[^1] dolor[^abc] sit[^1] amet\n\n[^1]: A footnote\n[^abc]: Another footnote";
269
+		$expected = '<p>Lorem ipsum<sup class="footnote" id="footnoteref_1"><a href="#footnote_1">1</a></sup> ' .
270
+			'dolor<sup class="footnote" id="footnoteref_2"><a href="#footnote_2">2</a></sup> ' .
271
+			'sit<sup class="footnote" id="footnoteref_3"><a href="#footnote_1">1</a></sup> amet</p>' .
272
+			'<div class="footnotes">' .
273
+			'<ol>' .
274
+			'<li value="1" id="footnote_1">A footnote <a href="#footnoteref_1" class="footnote-backref">↩︎</a><a href="#footnoteref_3" class="footnote-backref">↩︎</a></li>' .
275
+			'<li value="2" id="footnote_2">Another footnote <a href="#footnoteref_2" class="footnote-backref">↩︎</a></li>' .
276
+			'</ol>' .
277
+			'</div>';
278
+		$actual = $this->md($markdown);
279
+		$this->assertSame($expected, $actual);
280
+	}
281
+
282
+	public function test_abbreviations() {
283
+		$markdown = "Lorem ipsum HTML dolor HTML sit\n" .
284
+			"\n" .
285
+			"*[HTML]: Hypertext Markup Language";
286
+		$expected = '<p>Lorem ipsum <abbr title="Hypertext Markup Language">HTML</abbr> dolor <abbr title="Hypertext Markup Language">HTML</abbr> sit</p>';
287
+		$actual = $this->md($markdown);
288
+		$this->assertSame($expected, $actual);
289
+	}
290
+}

+ 0
- 1
phptest/InlineTests.php 查看文件

@@ -6,7 +6,6 @@ use PHPUnit\Framework\TestCase;
6 6
 require_once __DIR__ . '/../php/markdown.php';
7 7
 
8 8
 final class InlineTests extends TestCase {
9
-	/** @type {Markdown} */
10 9
 	private ?Markdown $parser = null;
11 10
 
12 11
 	protected function setUp(): void {

+ 8
- 8
phptest/TokenTests.php 查看文件

@@ -63,9 +63,9 @@ final class TokenTests extends TestCase {
63 63
 		$pattern = [
64 64
 			MDTokenType::Underscore,
65 65
 		];
66
-		$result = MDToken::findFirstTokens($tokens, $pattern);
66
+		$actual = MDToken::findFirstTokens($tokens, $pattern);
67 67
 		$expected = new MDTokenMatch([ $tokens[2] ], 2);
68
-		$this->assertEquals($expected, $result);
68
+		$this->assertEquals($expected, $actual);
69 69
 	}
70 70
 
71 71
 	public function test_findFirstTokens_optionalWhitespace1() {
@@ -82,9 +82,9 @@ final class TokenTests extends TestCase {
82 82
 			MDTokenType::META_OptionalWhitespace,
83 83
 			MDTokenType::URL,
84 84
 		];
85
-		$result = MDToken::findFirstTokens($tokens, $pattern);
85
+		$actual = MDToken::findFirstTokens($tokens, $pattern);
86 86
 		$expected = new MDTokenMatch([ $tokens[2], $tokens[3] ], 2);
87
-		$this->assertEquals($expected, $result);
87
+		$this->assertEquals($expected, $actual);
88 88
 	}
89 89
 
90 90
 	public function test_findFirstTokens_optionalWhitespace2() {
@@ -102,9 +102,9 @@ final class TokenTests extends TestCase {
102 102
 			MDTokenType::META_OptionalWhitespace,
103 103
 			MDTokenType::URL,
104 104
 		];
105
-		$result = MDToken::findFirstTokens($tokens, $pattern);
105
+		$actual = MDToken::findFirstTokens($tokens, $pattern);
106 106
 		$expected = new MDTokenmatch([ $tokens[2], $tokens[3], $tokens[4] ], 2);
107
-		$this->assertEquals($expected, $result);
107
+		$this->assertEquals($expected, $actual);
108 108
 	}
109 109
 
110 110
 	public function test_findPairedTokens() {
@@ -123,7 +123,7 @@ final class TokenTests extends TestCase {
123 123
 		$pattern = [
124 124
 			MDTokenType::Underscore,
125 125
 		];
126
-		$result = MDToken::findPairedTokens($tokens, $pattern, $pattern);
126
+		$actual = MDToken::findPairedTokens($tokens, $pattern, $pattern);
127 127
 		$expected = new MDPairedTokenMatch(
128 128
 			[ $tokens[2] ], // startTokens
129 129
 			[ $tokens[3] ], // contentTokens
@@ -133,7 +133,7 @@ final class TokenTests extends TestCase {
133 133
 			4, // endIndex
134 134
 			3 // totalLength
135 135
 		);
136
-		$this->assertEquals($expected, $result);
136
+		$this->assertEquals($expected, $actual);
137 137
 	}
138 138
 }
139 139
 ?>

+ 2
- 2
runphptests.sh 查看文件

@@ -1,6 +1,6 @@
1 1
 #!/bin/sh
2
-php lib/phpunit.phar \
2
+php lib/phpunit.phar --display-warnings --display-notices \
3 3
 	phptest/UtilsTests.php \
4 4
 	phptest/TokenTests.php \
5 5
 	phptest/InlineTests.php \
6
-
6
+	phptest/BlockTests.php \

+ 1
- 1
testjs.html 查看文件

@@ -463,7 +463,7 @@
463 463
 			document.addEventListener('DOMContentLoaded', onLoad);
464 464
 
465 465
 			function normalizeWhitespace(str) {
466
-				return str.replace(/\s+/g, ' ').replace(/(?:^\s+|\s+$)/g, '');
466
+				return str.replace(/\s+/gs, ' ').replace(/>\s+</gs, '><').trim();
467 467
 			}
468 468
 		</script>
469 469
 	</head>

正在加载...
取消
保存