github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/to-markdown/test/to-markdown-test.js (about) 1 /* global QUnit, test, equal, throws, asyncTest, start */ 2 3 'use strict'; 4 5 if (typeof module !== 'undefined' && module.exports) { 6 var toMarkdown = require('../index'); 7 } 8 9 // Test cases are in the format: [html, expectedMarkdown, message]; 10 function runTestCases(testCases) { 11 for (var i = 0; i < testCases.length; i++) { 12 var testCase = testCases[i]; 13 equal(toMarkdown(testCase[0]), testCase[1], testCase[2]); 14 } 15 } 16 17 QUnit.module('Markdown'); 18 19 test('paragraphs', function() { 20 runTestCases([ 21 ['<p>Lorem ipsum</p>', 'Lorem ipsum', 'p'], 22 ['<p>Lorem</p><p>ipsum</p>', 'Lorem\n\nipsum', 'Multiple ps'] 23 ]); 24 }); 25 26 test('emphasis', function() { 27 runTestCases([ 28 ['<b>Hello world</b>', '**Hello world**', 'b'], 29 ['<strong>Hello world</strong>', '**Hello world**', 'strong'], 30 ['<i>Hello world</i>', '_Hello world_', 'i'], 31 ['<em>Hello world</em>', '_Hello world_', 'em'], 32 ['<em>Hello</em> <em>world</em>', '_Hello_ _world_', 'Multiple ems'] 33 ]); 34 }); 35 36 test('code', function() { 37 runTestCases([ 38 ['<code>print()</code>', '`print()`'] 39 ]); 40 }); 41 42 test('headings', function() { 43 runTestCases([ 44 ['<h1>Hello world</h1>', '# Hello world', 'h1'], 45 ['<h3>Hello world</h3>', '### Hello world', 'h3'], 46 ['<h6>Hello world</h6>', '###### Hello world', 'h6'], 47 ['<h4><i>Hello</i> world</h4>', '#### _Hello_ world', 'h4 with child'], 48 ['<h8>Hello world</h8>', '<h8>Hello world</h8>', 'invalid heading'] 49 ]); 50 }); 51 52 test('horizontal rules', function() { 53 runTestCases([ 54 ['<hr />', '* * *', 'hr'], 55 ['<hr></hr>', '* * *', 'open/closed hr'] 56 ]); 57 }); 58 59 test('line breaks', function() { 60 runTestCases([ 61 ['Hello<br />world', 'Hello \nworld'] 62 ]); 63 }); 64 65 test('images', function() { 66 runTestCases([ 67 ['<img src="http://example.com/logo.png" />', '', 'img with no alt'], 68 ['<img src=logo.png>', '', 'img with relative src'], 69 ['<img src=logo.png alt="Example logo">', '', 'img with alt'], 70 ['<img>', '', 'img no src'] 71 ]); 72 }); 73 74 test('anchors', function() { 75 runTestCases([ 76 ['<a href="http://example.com/about">About us</a>', '[About us](http://example.com/about)', 'a'], 77 ['<a href="http://example.com/about" title="About this company">About us</a>', '[About us](http://example.com/about "About this company")', 'a with title'], 78 ['<a id="donuts3">About us</a>', '<a id="donuts3">About us</a>', 'a with no src'], 79 ['<a href="http://example.com/about"><span>About us</span></a>', '[<span>About us</span>](http://example.com/about)', 'with a span'] 80 ]); 81 }); 82 83 test('pre/code blocks', function() { 84 runTestCases([ 85 [ 86 ['<pre><code>def hello_world', 87 ' # 42 < 9001', 88 ' "Hello world!"', 89 'end</code></pre>'].join('\n'), 90 91 [' def hello_world', 92 ' # 42 < 9001', 93 ' "Hello world!"', 94 ' end'].join('\n') 95 ], 96 [ 97 ['<pre><code>def foo', 98 ' # 42 < 9001', 99 ' \'Hello world!\'', 100 'end</code></pre>', 101 '<p>next:</p>', 102 '<pre><code>def bar', 103 ' # 42 < 9001', 104 ' \'Hello world!\'', 105 'end</code></pre>'].join('\n'), 106 107 [' def foo', 108 ' # 42 < 9001', 109 ' \'Hello world!\'', 110 ' end', 111 '', 112 'next:', 113 '', 114 ' def bar', 115 ' # 42 < 9001', 116 ' \'Hello world!\'', 117 ' end'].join('\n'), 118 119 'Multiple pre/code blocks' 120 ], 121 ['<pre>preformatted</pre>', '<pre>preformatted</pre>', 'Plain pre'] 122 ]); 123 }); 124 125 test('lists', function() { 126 runTestCases([ 127 ['1986. What a great season.', '1986\\. What a great season.', 'ol triggers are escaped'], 128 ['<ol>\n\t<li>Hello world</li>\n\t<li>Foo bar</li>\n</ol>', '1. Hello world\n2. Foo bar', 'ol'], 129 ['<ul>\n\t<li>Hello world</li>\n\t<li>Foo bar</li>\n</ul>', '* Hello world\n* Foo bar', 'ul'], 130 [ 131 ['<ul>', 132 ' <li>Hello world</li>', 133 ' <li>Lorem ipsum</li>', 134 '</ul>', 135 '<ul>', 136 ' <li>Hello world</li>', 137 ' <li>Lorem ipsum</li>', 138 '</ul>'].join('\n'), 139 140 ['* Hello world', 141 '* Lorem ipsum', 142 '', 143 '* Hello world', 144 '* Lorem ipsum'].join('\n'), 145 146 'Multiple uls' 147 ], 148 [ 149 '<ul><li><p>Hello world</p></li><li>Lorem ipsum</li></ul>', 150 '* Hello world\n\n* Lorem ipsum', 151 'ul with p' 152 ], 153 [ 154 ['<ol>', 155 ' <li>', 156 ' <p>This is a list item with two paragraphs.</p>', 157 ' <p>Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>', 158 ' </li>', 159 ' <li>', 160 ' <p>Suspendisse id sem consectetuer libero luctus adipiscing.</p>', 161 ' </li>', 162 '</ol>'].join('\n'), 163 164 ['1. This is a list item with two paragraphs.', 165 '', 166 ' Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.', 167 '', 168 '2. Suspendisse id sem consectetuer libero luctus adipiscing.'].join('\n'), 169 170 'ol with multiple ps' 171 ], 172 [ 173 ['<ul>', 174 ' <li>This is a list item at root level</li>', 175 ' <li>This is another item at root level</li>', 176 ' <li>', 177 ' <ul>', 178 ' <li>This is a nested list item</li>', 179 ' <li>This is another nested list item</li>', 180 ' <li>', 181 ' <ul>', 182 ' <li>This is a deeply nested list item</li>', 183 ' <li>This is another deeply nested list item</li>', 184 ' <li>This is a third deeply nested list item</li>', 185 ' </ul>', 186 ' </li>', 187 ' </ul>', 188 ' </li>', 189 ' <li>This is a third item at root level</li>', 190 '</ul>'].join('\n'), 191 192 ['* This is a list item at root level', 193 '* This is another item at root level', 194 '* * This is a nested list item', 195 ' * This is another nested list item', 196 ' * * This is a deeply nested list item', 197 ' * This is another deeply nested list item', 198 ' * This is a third deeply nested list item', 199 '* This is a third item at root level'].join('\n'), 200 201 'Nested uls' 202 ], 203 [ 204 ['<ul>', 205 ' <li>This is a list item at root level</li>', 206 ' <li>This is another item at root level</li>', 207 ' <li>', 208 ' <ol>', 209 ' <li>This is a nested list item</li>', 210 ' <li>This is another nested list item</li>', 211 ' <li>', 212 ' <ul>', 213 ' <li>This is a deeply nested list item</li>', 214 ' <li>This is another deeply nested list item</li>', 215 ' <li>This is a third deeply nested list item</li>', 216 ' </ul>', 217 ' </li>', 218 ' </ol>', 219 ' </li>', 220 ' <li>This is a third item at root level</li>', 221 '</ul>'].join('\n'), 222 223 ['* This is a list item at root level', 224 '* This is another item at root level', 225 '* 1. This is a nested list item', 226 ' 2. This is another nested list item', 227 ' 3. * This is a deeply nested list item', 228 ' * This is another deeply nested list item', 229 ' * This is a third deeply nested list item', 230 '* This is a third item at root level'].join('\n'), 231 232 'Nested ols' 233 ], 234 [ 235 ['<ul>', 236 ' <li>', 237 ' <p>A list item with a blockquote:</p>', 238 ' <blockquote>', 239 ' <p>This is a blockquote inside a list item.</p>', 240 ' </blockquote>', 241 ' </li>', 242 '</ul>'].join('\n'), 243 244 ['* A list item with a blockquote:', 245 '', 246 ' > This is a blockquote inside a list item.'].join('\n'), 247 248 'ul with blockquote' 249 ] 250 ]); 251 }); 252 253 test('blockquotes', function() { 254 runTestCases([ 255 [ 256 ['<blockquote>', 257 ' <p>This is a blockquote with two paragraphs.</p>', 258 '', 259 ' <p>Donec sit amet nisl.</p>', 260 '</blockquote>'].join('\n'), 261 262 ['> This is a blockquote with two paragraphs.', 263 '> ', 264 '> Donec sit amet nisl.'].join('\n'), 265 266 'blockquote with two ps' 267 ], 268 [ 269 ['<blockquote>', 270 ' <p>This is the first level of quoting.</p>', 271 '', 272 ' <blockquote>', 273 ' <p>This is nested blockquote.</p>', 274 ' </blockquote>', 275 '', 276 ' <p>Back to the first level.</p>', 277 '</blockquote>'].join('\n'), 278 279 ['> This is the first level of quoting.', 280 '> ', 281 '> > This is nested blockquote.', 282 '> ', 283 '> Back to the first level.'].join('\n'), 284 285 'Nested blockquotes' 286 ], 287 [ 288 ['<blockquote>', 289 ' <h2>This is a header.</h2>', 290 ' <ol>', 291 ' <li>This is the first list item.</li>', 292 ' <li>This is the second list item.</li>', 293 ' </ol>', 294 ' <p>Here\'s some example code:</p>', 295 ' <pre><code>return 1 < 2 ? shell_exec(\'echo $input | $markdown_script\') : 0;</code></pre>', 296 '</blockquote>'].join('\n'), 297 298 ['> ## This is a header.', 299 '> ', 300 '> 1. This is the first list item.', 301 '> 2. This is the second list item.', 302 '> ', 303 '> Here\'s some example code:', 304 '> ', 305 '> return 1 < 2 ? shell_exec(\'echo $input | $markdown_script\') : 0;'].join('\n'), 306 307 'html in blockquote' 308 ] 309 ]); 310 }); 311 312 test('block-level', function () { 313 runTestCases([ 314 ['<div>Hello</div><div>world</div>', '<div>Hello</div>\n\n<div>world</div>', 'divs separated by \\n\\n'], 315 ['<div><em>hello</em></div>', '<div>_hello_</div>'] 316 ]); 317 }); 318 319 test('comments', function () { 320 equal(toMarkdown('<!-- comment -->'), '', 'comments removed'); 321 }); 322 323 test('leading/trailing whitespace', function() { 324 runTestCases([ 325 [ 326 '<p>I <a href="http://example.com">need</a> <a href="http://www.example.com">more</a> spaces!</p>', 327 'I [need](http://example.com) [more](http://www.example.com) spaces!', 328 'Whitespace between inline elements' 329 ], 330 ['<h1>\n Header text', '# Header text', 'Leading whitespace in h1'], 331 [ 332 ['<ol>', 333 ' <li>Chapter One', 334 ' <ol>', 335 ' <li>Section One</li>', 336 ' <li>Section Two </li>', 337 ' <li>Section Three </li>', 338 ' </ol>', 339 ' </li>', 340 ' <li>Chapter Two</li>', 341 ' <li>Chapter Three </li>', 342 '</ol>'].join('\n'), 343 344 ['1. Chapter One', 345 ' 1. Section One', 346 ' 2. Section Two', 347 ' 3. Section Three', 348 '2. Chapter Two', 349 '3. Chapter Three'].join('\n'), 350 351 'Trailing whitespace in li' 352 ], 353 [ 354 ['<ul>', 355 ' <li>', // Multilined 356 ' Foo ', 357 ' </li>', 358 ' <li>', // Bizarre formatting 359 ' <strong>Bar </strong> </li>', 360 ' <li>Baz</li>', 361 '</ul>', 362 '<ol>', 363 ' <li> Hello', 364 ' world', 365 ' </li>', 366 '</ol>'].join('\n'), 367 368 ['* Foo', 369 '* **Bar**', 370 '* Baz', 371 '', 372 '1. Hello world'].join('\n') 373 ], 374 [ 375 'Hello world.<em> Foo </em><strong>bar </strong>', 376 'Hello world. _Foo_ **bar**', 377 'Whitespace in inline elements' 378 ] 379 ]); 380 }); 381 382 test('blank', function () { 383 runTestCases([ 384 ['<div></div>', '', 'Blank div'], 385 ['<em></em>', '', 'Blank em'], 386 ['<strong><br></strong>', '', 'Blank strong with br'], 387 ['<a href="#foo"></a>', '[](#foo)', 'Blank a'], 388 ]); 389 }); 390 391 test('custom converters', function() { 392 var html, converter, md = '*Hello world*'; 393 var replacement = function (innerHTML) { 394 return '*' + innerHTML + '*'; 395 }; 396 397 html = '<span>Hello world</span>'; 398 converter = { 399 filter: 'span', 400 replacement: replacement 401 }; 402 equal(toMarkdown(html, {converters: [converter]}), md, 'Custom filter string'); 403 404 html = '<span>Hello world</span>'; 405 converter = { 406 filter: ['span'], 407 replacement: replacement 408 }; 409 equal(toMarkdown(html, {converters: [converter]}), md, 'Custom filter array'); 410 411 html = '<span style="font-style: italic">Hello world</span>'; 412 converter = { 413 filter: function (node) { 414 return node.tagName === 'SPAN' && /italic/i.test(node.style.fontStyle); 415 }, 416 replacement: replacement 417 }; 418 equal(toMarkdown(html, {converters: [converter]}), md, 'Custom filter function'); 419 }); 420 421 test('invalid input', function () { 422 throws(function () { toMarkdown(null); }, /null is not a string/, 'null input'); 423 throws(function () { toMarkdown(void(0)); }, /undefined is not a string/, 'undefined input'); 424 425 throws(function () { toMarkdown(null); }, function (e) { 426 return e.name === 'TypeError'; 427 }, 'error type'); 428 }); 429 430 asyncTest('img[onerror]', 1, function () { 431 start(); 432 equal(toMarkdown('>\'>"><img src=x onerror="(function () { ok(true); })()">'), '>\'>">', 'We expect img[onerror] functions not to run'); 433 });