/* global QUnit, test, expect, equal, throws, asyncTest, start */
'use strict'
if (typeof module !== 'undefined' && module.exports) {
var toMarkdown = require('../index')
}
// Test cases are in the format: [html, expectedMarkdown, message]
function runTestCases (testCases) {
for (var i = 0; i < testCases.length; i++) {
var testCase = testCases[i]
equal(toMarkdown(testCase[0]), testCase[1], testCase[2])
}
}
QUnit.module('Markdown')
test('paragraphs', function () {
runTestCases([
['
Lorem ipsum
', 'Lorem ipsum', 'p'],
['Lorem
ipsum
', 'Lorem\n\nipsum', 'Multiple ps']
])
})
test('emphasis', function () {
runTestCases([
['Hello world', '**Hello world**', 'b'],
['Hello world', '**Hello world**', 'strong'],
['Hello world', '_Hello world_', 'i'],
['Hello world', '_Hello world_', 'em'],
['Hello world', '_Hello_ _world_', 'Multiple ems']
])
})
test('code', function () {
runTestCases([
['print()', '`print()`']
])
})
test('headings', function () {
runTestCases([
['Hello world
', '# Hello world', 'h1'],
['Hello world
', '### Hello world', 'h3'],
['Hello world
', '###### Hello world', 'h6'],
['Hello world
', '#### _Hello_ world', 'h4 with child'],
['Hello world', 'Hello world', 'invalid heading']
])
})
test('horizontal rules', function () {
runTestCases([
['
', '* * *', 'hr'],
['
', '* * *', 'open/closed hr']
])
})
test('line breaks', function () {
runTestCases([
['Hello
world', 'Hello \nworld']
])
})
test('images', function () {
runTestCases([
['
', '', 'img with no alt'],
['
', '', 'img with relative src'],
['
', '', 'img with alt'],
['
', '', 'img no src']
])
})
test('anchors', function () {
runTestCases([
['About us', '[About us](http://example.com/about)', 'a'],
['About us', '[About us](http://example.com/about "About this company")', 'a with title'],
['About us', 'About us', 'a with no src'],
['About us', '[About us](http://example.com/about)', 'with a span']
])
})
test('pre/code blocks', function () {
runTestCases([
[
['def hello_world',
' # 42 < 9001',
' "Hello world!"',
'end
'].join('\n'),
[' def hello_world',
' # 42 < 9001',
' "Hello world!"',
' end'].join('\n')
],
[
['def foo',
' # 42 < 9001',
" 'Hello world!'",
'end
',
'next:
',
'def bar',
' # 42 < 9001',
" 'Hello world!'",
'end
'].join('\n'),
[' def foo',
' # 42 < 9001',
" 'Hello world!'",
' end',
'',
'next:',
'',
' def bar',
' # 42 < 9001',
" 'Hello world!'",
' end'].join('\n'),
'Multiple pre/code blocks'
],
['preformatted
', 'preformatted
', 'Plain pre']
])
})
test('lists', function () {
runTestCases([
['1986. What a great season.', '1986\\. What a great season.', 'ol triggers are escaped'],
['\n\t- Hello world
\n\t- Foo bar
\n
', '1. Hello world\n2. Foo bar', 'ol'],
['\n\t- Hello world
\n\t- Foo bar
\n
', '* Hello world\n* Foo bar', 'ul'],
[
['',
' - Hello world
',
' - Lorem ipsum
',
'
',
'',
' - Hello world
',
' - Lorem ipsum
',
'
'].join('\n'),
['* Hello world',
'* Lorem ipsum',
'',
'* Hello world',
'* Lorem ipsum'].join('\n'),
'Multiple uls'
],
[
'',
'* Hello world\n\n* Lorem ipsum',
'ul with p'
],
[
['',
' - ',
'
This is a list item with two paragraphs.
',
' Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
',
' ',
' - ',
'
Suspendisse id sem consectetuer libero luctus adipiscing.
',
' ',
'
'].join('\n'),
['1. This is a list item with two paragraphs.',
'',
' Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.',
'',
'2. Suspendisse id sem consectetuer libero luctus adipiscing.'].join('\n'),
'ol with multiple ps'
],
[
['',
' - This is a list item at root level
',
' - This is another item at root level
',
' - ',
'
',
' - This is a nested list item
',
' - This is another nested list item
',
' - ',
'
',
' - This is a deeply nested list item
',
' - This is another deeply nested list item
',
' - This is a third deeply nested list item
',
'
',
' ',
'
',
' ',
' - This is a third item at root level
',
'
'].join('\n'),
['* This is a list item at root level',
'* This is another item at root level',
'* * This is a nested list item',
' * This is another nested list item',
' * * This is a deeply nested list item',
' * This is another deeply nested list item',
' * This is a third deeply nested list item',
'* This is a third item at root level'].join('\n'),
'Nested uls'
],
[
['',
' - This is a list item at root level
',
' - This is another item at root level
',
' - ',
'
',
' - This is a nested list item
',
' - This is another nested list item
',
' - ',
'
',
' - This is a deeply nested list item
',
' - This is another deeply nested list item
',
' - This is a third deeply nested list item
',
'
',
' ',
'
',
' ',
' - This is a third item at root level
',
'
'].join('\n'),
['* This is a list item at root level',
'* This is another item at root level',
'* 1. This is a nested list item',
' 2. This is another nested list item',
' 3. * This is a deeply nested list item',
' * This is another deeply nested list item',
' * This is a third deeply nested list item',
'* This is a third item at root level'].join('\n'),
'Nested ols'
],
[
[''].join('\n'),
['* A list item with a blockquote:',
'',
' > This is a blockquote inside a list item.'].join('\n'),
'ul with blockquote'
]
])
})
test('blockquotes', function () {
runTestCases([
[
['',
' This is a blockquote with two paragraphs.
',
'',
' Donec sit amet nisl.
',
'
'].join('\n'),
['> This is a blockquote with two paragraphs.',
'> ',
'> Donec sit amet nisl.'].join('\n'),
'blockquote with two ps'
],
[
['',
' This is the first level of quoting.
',
'',
' ',
' This is nested blockquote.
',
'
',
'',
' Back to the first level.
',
'
'].join('\n'),
['> This is the first level of quoting.',
'> ',
'> > This is nested blockquote.',
'> ',
'> Back to the first level.'].join('\n'),
'Nested blockquotes'
],
[
['',
' This is a header.
',
' ',
' - This is the first list item.
',
' - This is the second list item.
',
'
',
" Here's some example code:
",
" return 1 < 2 ? shell_exec('echo $input | $markdown_script') : 0;
",
'
'].join('\n'),
['> ## This is a header.',
'> ',
'> 1. This is the first list item.',
'> 2. This is the second list item.',
'> ',
"> Here's some example code:",
'> ',
"> return 1 < 2 ? shell_exec('echo $input | $markdown_script') : 0;"].join('\n'),
'html in blockquote'
]
])
})
test('block-level', function () {
runTestCases([
['Hello
world
', 'Hello
\n\nworld
', 'divs separated by \\n\\n'],
['hello
', '_hello_
']
])
})
test('comments', function () {
equal(toMarkdown(''), '', 'comments removed')
})
test('leading/trailing whitespace', function () {
runTestCases([
[
'I need more spaces!
',
'I [need](http://example.com) [more](http://www.example.com) spaces!',
'Whitespace between inline elements'
],
['\n Header text', '# Header text', 'Leading whitespace in h1'],
[
['',
' - Chapter One',
'
',
' - Section One
',
' - Section Two
',
' - Section Three
',
'
',
' ',
' - Chapter Two
',
' - Chapter Three
',
'
'].join('\n'),
['1. Chapter One',
' 1. Section One',
' 2. Section Two',
' 3. Section Three',
'2. Chapter Two',
'3. Chapter Three'].join('\n'),
'Trailing whitespace in li'
],
[
['',
' - ', // Multilined
' Foo ',
'
',
' - ', // Bizarre formatting
' Bar
',
' - Baz
',
'
',
'',
' - Hello',
' world',
'
',
'
'].join('\n'),
['* Foo',
'* **Bar**',
'* Baz',
'',
'1. Hello world'].join('\n')
],
[
'Hello world. Foo bar ',
'Hello world. _Foo_ **bar**',
'Whitespace in inline elements'
],
[
'
Hello world.
',
'#  Hello world.',
'Whitespace and void elements'
],
[
'Hello Hello Hello',
'Hello **[Hello](https://www.google.com)** Hello',
'Whitespace in bold links.'
]
])
})
test('blank', function () {
runTestCases([
['
', '', 'Blank div'],
['', '', 'Blank em'],
['
', '', 'Blank strong with br'],
['', '[](#foo)', 'Blank a']
])
})
test('custom converters', function () {
var html
var converter
var md = '*Hello world*'
var replacement = function (innerHTML) {
return '*' + innerHTML + '*'
}
html = 'Hello world'
converter = {
filter: 'span',
replacement: replacement
}
equal(toMarkdown(html, {converters: [converter]}), md, 'Custom filter string')
html = 'Hello world'
converter = {
filter: ['span'],
replacement: replacement
}
equal(toMarkdown(html, {converters: [converter]}), md, 'Custom filter array')
html = 'Hello world'
converter = {
filter: function (node) {
return node.tagName === 'SPAN' && /italic/i.test(node.style.fontStyle)
},
replacement: replacement
}
equal(toMarkdown(html, {converters: [converter]}), md, 'Custom filter function')
})
test('invalid input', function () {
throws(function () { toMarkdown(null) }, /null is not a string/, 'null input')
throws(function () { toMarkdown(void (0)) }, /undefined is not a string/, 'undefined input')
throws(function () { toMarkdown(null) }, function (e) {
return e.name === 'TypeError'
}, 'error type')
})
asyncTest('img[onerror]', 1, function () {
start()
equal(toMarkdown('>\'>">
'), '>\'>">', 'We expect img[onerror] functions not to run')
})
test('malformed documents', function () {
expect(0) // just make sure to-markdown doesn't crash
var html = ''
toMarkdown(html)
})
test('empty string', function () {
runTestCases([
['', '']
])
})