import { render, type SlimdownExtension } from './index.js'; import test from 'ava'; const removeWhitespaces = (txt: string) => txt.replace(/\s+/g, ''); test('header', (t) => { const expected = '

Hello world

'; const html = render('# Hello world'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('single underscore', (t) => { const expected = '

Hello_world

'; const html = render('Hello_world'); const html2 = render('Hello\\_world'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); t.is(removeWhitespaces(html2), removeWhitespaces(expected)); }); test('double underscores', (t) => { const expected = '

here_a_test

'; const html = render('here\\_a\\_test'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('italics', (t) => { const expected = '

This is italics.

'; const html = render('This is _italics_.'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('superscript', (t) => { const expected = '

This is the 1st test, and this is the 2nd version. But also consider a2 + b2 = c2.

'; const html = render( 'This is the 1^st^ test, and this is the 2^nd^ version. But also consider a^2^ + b^2^ = c^2^.', ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('subscript', (t) => { const expected = '

This is italics and this is a1 or C2.

'; const html = render('This is _italics_ and this is a~1~ or C~2~.'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('footnote', (t) => { const expected = `

Here is a simple footnote[1]. With some additional text after it.


  1. My reference.
`; const html = render( `Here is a simple footnote[^1]. With some additional text after it. [^1]: My reference.`, ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('code', (t) => { const expected = '

This is italics and this is _italics_ too.

'; const html = render('This is `italics` and this is `_italics_` too.'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('multiline codeblock', (t) => { const expected = `
## Table example

| Tables        | Are           | Cool  |
|---------------|:-------------:|------:|
| col 3 is      | right-aligned | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |
`; const html = render(` \`\`\`md ## Table example | Tables | Are | Cool | |---------------|:-------------:|------:| | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | \`\`\` `); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('ul', (t) => { const expected = ''; const html = render(`- Item 1\n- Item 2\n- Item 3`); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('ul using +', (t) => { const expected = ''; const html = render(`+ Item 1\n+ Item 2\n+ Item 3`); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('ul using *', (t) => { const expected = ''; const html = render(`* Item 1\n* Item 2\n* Item 3`); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('nested ul + ul', (t) => { const expected = ''; const html = render( `- Item 1\n - Item 1.1\n - Item 1.2\n - Item 1.3\n- Item 2\n- Item 3`, ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('nested ul + ol', (t) => { const expected = ''; const html = render( `- Item 1\n 1. Item 1.1\n 2. Item 1.2\n 3. Item 1.3\n- Item 2\n- Item 3`, ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('ol', (t) => { const expected = '
  1. Item 1
  2. Item 2
  3. Item 3
'; const html = render(`1. Item 1\n2. Item 2\n3. Item 3`); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('nested ol + ol', (t) => { const expected = '
  1. Item 1
    1. Item 1.1
    2. Item 1.2
    3. Item 1.3
  2. Item 2
  3. Item 3
'; const html = render( `1. Item 1\n 1. Item 1.1\n 2. Item 1.2\n 3. Item 1.3\n2. Item 2\n3. Item 3`, ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('nested ol + ul', (t) => { const expected = '
  1. Item 1
  2. Item 2
  3. Item 3
'; const html = render( `1. Item 1\n - Item 1.1\n - Item 1.2\n - Item 1.3\n2. Item 2\n3. Item 3`, ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('table 1', (t) => { const table = ` | Threat \\ Context | rainy | sunny | |------------------|------------|------------| | terrorist | scenario 1 | scenario 2 | | criminal | scenario 3 | scenario 4 | `; const expected = `
Threat \\ Contextrainysunny
terroristscenario 1scenario 2
criminalscenario 3scenario 4
`; const html = render(table); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('table 2', (t) => { const table = ` | Threat \\ Context | rainy | sunny | | ---------------- | ---------- | ---------- | | terrorist | scenario 1 | scenario 2 | | criminal | scenario 3 | scenario 4 | `; const expected = `
Threat \\ Contextrainysunny
terroristscenario 1scenario 2
criminalscenario 3scenario 4
`; const html = render(table); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing strong in own paragraph', (t) => { const md = `An **indie electronica music** bundle. **Featuring** songs by ... Pay what you want for Music`; const generated = render(md); const expected = `

An indie electronica music bundle.

Featuring songs by ...

Pay what you want for Music

`; t.is(generated, expected); }); test('parsing longer text', (t) => { const md = `# Title To use **Slimdown**, grap it from [npm](https://www.npmjs.com/package/slimdown-js) or *fork* the project on [GitHub](https://github.com/erikvullings/slimdown-js). * One * Two * Three ## Underscores my\\_var\\_is ## Subhead One **two** three **four** five. One __two__ three _four_ five __six__ seven _eight_. 1. One 2. Two 3. Three More text with \`inline($code);\` sample. > A block quote > across two lines. More text...`; const expected = `

Title

To use Slimdown, grap it from npm or fork the project on GitHub.

Underscores

my_var_is

Subhead

One two three four five.

One two three four five six seven eight.

  1. One
  2. Two
  3. Three

More text with inline($code); sample.

A block quote
across two lines.

More text...

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('headings have no id attribute by default', (t) => { const md = `# Hello world\n\n## Setup`; const html = render(md); t.false(html.includes('id=')); }); test('headings have no id attribute when headingIds is false', (t) => { const md = `# Hello world`; const html = render(md, { headingIds: false }); t.false(html.includes('id=')); }); test('headingIds adds a slugified id to each heading', (t) => { const md = `# Hello World\n\n## Second Level Heading`; const html = render(md, { headingIds: true }); t.true(html.includes('

Hello World

')); t.true(html.includes('

Second Level Heading

')); }); test('headingIds slugifies rendered inline content, not raw markdown', (t) => { const md = `## **Setup**`; const html = render(md, { headingIds: true }); t.true(html.includes('

Setup

')); }); test('headingIds falls back to "section" for symbol-only headings', (t) => { const md = `# !!!`; const html = render(md, { headingIds: true }); t.true(html.includes('

')); }); test('headingIds strips accents to base Latin letters', (t) => { const md = `# Café Déjà Vu`; const html = render(md, { headingIds: true }); t.true(html.includes('

Café Déjà Vu

')); }); test('headingIds appends -2, -3 suffixes for duplicate slugs', (t) => { const md = `# Overview\n\n## Overview\n\n### Overview`; const html = render(md, { headingIds: true }); t.true(html.includes('

Overview

')); t.true(html.includes('

Overview

')); t.true(html.includes('

Overview

')); }); test('headingIds keeps slug counts scoped to a single render call', (t) => { const first = render(`# Overview\n\n## Overview`, { headingIds: true }); const second = render(`# Overview`, { headingIds: true }); t.true(first.includes('

Overview

')); t.true(first.includes('

Overview

')); t.true(second.includes('

Overview

')); t.false(second.includes('id="overview-2"')); }); test('parsing links with underscores', (t) => { const md = `# Links fail with underscores [Test Link](http://www.google.com/?some_param=another_value)`; const expected = `

Links fail with underscores

Test Link

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing images', (t) => { const md = `NS logo image: ![ns logo](https://www.ns.nl/static/generic/2.49.1/images/nslogo.svg)`; const expected = `

NS logo image: ns logo

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing base64 images with empty alt text', (t) => { const md = `![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA)`; const expected = `

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing base64 images with empty alt text inside a table', (t) => { const md = `| Image | |-------| | ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA) |`; const expected = `
Image
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing code blocks', (t) => { const md = `# Code example \`\`\` Tab indented codeblock \`\`\` `; const expected = `

Code example

Tab indented codeblock
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing inline code', (t) => { const md = `This is \`inline A & B\` code.`; const expected = `This is inline A & B code.`; const html = render(md, true); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing inline HTML code', (t) => { const md = `This is \`

An HTML paragrahp

\` code.`; const expected = `This is <p>An HTML paragrahp</p> code.`; const html = render(md, true); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('bypassing HTML code', (t) => { const md = `An HTML paragrahp`; const expected = `An HTML paragrahp`; const html = render(md, true); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parsing tables', (t) => { const md = `# Table example | Tables | Are | Cool | |---------------|:-------------:|------:| | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | `; const expected = `

Table example

Tables Are Cool
col 3 is right-aligned $1600
col 2 is centered $12
zebra stripes are neat $1
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('removing paragraphs', (t) => { const expected = 'Hello world'; const html = render('Hello world', true); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('do not remove paragraphs for longer text', (t) => { const expected = `

Hello world

How are you?

`; const html = render( `# Hello world How are you?`, true, ); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('creating links', (t) => { const md = 'This is a [link](https://www.google.com).'; const expected = 'This is a link.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating external links', (t) => { const md = 'This is a [link](https://www.google.com).'; const expected = 'This is a link.'; const html = render(md, true, true); t.is(html.trim(), expected); }); test('creating links with underscores', (t) => { const md = 'This is a [link](https://my_test_page.com).'; const expected = 'This is a link.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating emphasized text', (t) => { const md = 'This is _emphasized_ text.'; const expected = 'This is emphasized text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating emphasized text 2', (t) => { const md = 'This is *emphasized* text.'; const expected = 'This is emphasized text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating strong text', (t) => { const md = 'This is **strong** text.'; const expected = 'This is strong text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating strong text 2', (t) => { const md = 'This is __strong__ text.'; const expected = 'This is strong text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating strong and empasized text', (t) => { const md = 'This is ***strong and emphasized*** text.'; const expected = 'This is strong and emphasized text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating strong and empasized text 2', (t) => { const md = 'This is ___strong and emphasized___ text.'; const expected = 'This is strong and emphasized text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating deleted text', (t) => { const md = 'This is ~~deleted~~ text.'; const expected = 'This is deleted text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating quotes', (t) => { const md = 'This is a quote: :"quoted": text.'; const expected = 'This is a quote: quoted text.'; const html = render(md, true); t.is(html.trim(), expected); }); test('creating block quotes', (t) => { const md = '> This is a blockquoted text.'; const expected = '
This is a blockquoted text.
'; const html = render(md, true); t.is(html.trim(), expected); }); test('complex nested ol with ul - continuous numbered list', (t) => { const md = `1. First item - Nested bullet 1 - Nested bullet 2 2. Second item - Another nested bullet 3. Third item`; const expected = `
  1. First item
  2. Second item
  3. Third item
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('complex nested ul with ol - continuous bullet list', (t) => { const md = `- First item 1. Nested number 1 2. Nested number 2 - Second item 1. Another nested number - Third item`; const expected = ``; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('triple nested lists', (t) => { const md = `1. Level 1 item 1 - Level 2 item 1 1. Level 3 item 1 2. Level 3 item 2 - Level 2 item 2 2. Level 1 item 2`; const expected = `
  1. Level 1 item 1
  2. Level 1 item 2
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('real world complex nested list', (t) => { const md = `1. **First Section:** - **Subsection A:** Description A - **Subsection B:** Description B 2. **Second Section:** - **Subsection C:** Description C - **Subsection D:** Description D`; const expected = `
  1. First Section:
  2. Second Section:
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); // Phase 1 feature tests test('inline math support', (t) => { const md = 'The equation $E = mc^2$ is famous.'; const expected = '

The equation E = mc^2 is famous.

'; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('block math support', (t) => { const md = `Here's a block equation: $$ \\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi} $$ That's Gaussian integral.`; const expected = `

Here's a block equation:

\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}

That's Gaussian integral.

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('task list with checked items', (t) => { const md = `- [x] Completed task - [ ] Incomplete task - [X] Another completed task`; const expected = ``; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('nested task lists', (t) => { const md = `- [x] Main task - [ ] Subtask 1 - [x] Subtask 2 - [ ] Another main task`; const expected = ``; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('definition lists', (t) => { const md = `Technology : Computer science field Science : Study of natural world`; const expected = `

Technology
Computer science field

Science
Study of natural world

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('no definition lists for regular colons', (t) => { const md = `Technology: Computer science field Science: Study of natural world`; const expected = `

Technology: Computer science field

Science:Study of natural world

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('no definition lists for math', (t) => { const md = `$15 : 3 = 5$`; const expected = `

15 : 3 = 5

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('table with empty cells not merged', (t) => { const md = `| Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Value | | End | | | Middle | |`; const expected = `
Header 1 Header 2 Header 3
Value End
Middle
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('table with column spanning', (t) => { const md = `| Header 1 | Header 2|| | Header 3 | |----------|----------|----------| | Cell 1 | Spanning|| | Cell | | Normal | Cell | Cell |`; const expected = `
Header 1 Header 2 Header 3
Cell 1 Spanning Cell
Normal Cell Cell
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('table with caption', (t) => { const md = `[Table Caption] | Name | Age | |------|-----| | John | 25 | | Jane | 30 |`; const expected = `
Table Caption
NameAge
John25
Jane30
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('math expressions with special characters', (t) => { const md = `Complex math: $\\sum_{i=1}^{n} x_i < \\infty$ and block math: $$ f(x) = \\begin{cases} x^2 & \\text{if } x \\geq 0 \\\\ -x^2 & \\text{if } x < 0 \\end{cases} $$`; const expected = `

Complex math: \\sum_{i=1}^{n} x_i < \\infty and block math:

f(x) = \\begin{cases} x^2 & \\text{if } x \\geq 0 \\\\ -x^2 & \\text{if } x < 0 \\end{cases}
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('mixed content with all Phase 1 features', (t) => { const md = `# Math and Tasks Here's some inline math $a^2 + b^2 = c^2$ and a task list: - [x] Learn math - [ ] Practice LaTeX: $\\int_0^1 x dx = \\frac{1}{2}$ Technology : Computer science field Science : Study of natural world [Data Table] | Name | Score|| | Total | |------|------|------| | Test | 85 | 95 |`; const expected = `

Math and Tasks

Here's some inline math a^2 + b^2 = c^2 and a task list:

Technology
Computer science field

Science
Study of natural world

Data Table
NameScoreTotal
Test8595
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('decimal numbers should not be converted to ordered lists', (t) => { const md = '100.000-1.000.000'; const expected = '

100.000-1.000.000

'; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('mix of decimal numbers and actual ordered list', (t) => { const md = `100.000-1.000.000 1. This is a real list item 2. This is another real list item Price range: 50.99-99.99`; const expected = `

100.000-1.000.000

  1. This is a real list item
  2. This is another real list item

Price range: 50.99-99.99

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('horizontal rule with three dashes', (t) => { const expected = '

before

\n
\n

after

'; const html = render('before\n\n---\n\nafter'); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('horizontal rule variations', (t) => { const expected1 = '

text

\n
\n

more

'; const html1 = render('text\n\n---\n\nmore'); t.is(removeWhitespaces(html1), removeWhitespaces(expected1)); const expected2 = '

text

\n
\n

more

'; const html2 = render('text\n\n----\n\nmore'); t.is(removeWhitespaces(html2), removeWhitespaces(expected2)); const expected3 = '

text

\n
\n

more

'; const html3 = render('text\n\n-----\n\nmore'); t.is(removeWhitespaces(html3), removeWhitespaces(expected3)); }); test('mixed ordered and unordered lists with text after', (t) => { const md = `1. First item 2. Second item 3. Third item - Unordered item - Another item - Last item More text`; const expected = `
  1. First item
  2. Second item
  3. Third item

More text

`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('mixed unordered and ordered lists', (t) => { const md = `- First bullet - Second bullet 1. First number 2. Second number - Back to bullets - Another bullet`; const expected = `
  1. First number
  2. Second number
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('codeblock extension', (t) => { const extension: SlimdownExtension = { renderCodeBlock: ({ lang, code, escapeHtml }) => lang === 'mermaid' ? `
${escapeHtml(code)}
` : undefined, }; const html = render( `\`\`\`mermaid graph TD A --> B \`\`\``, { extensions: [extension] }, ); t.is( removeWhitespaces(html), removeWhitespaces( '
graph TD\n A --> B
', ), ); }); test('codeblock extension fallback', (t) => { const extension: SlimdownExtension = { renderCodeBlock: () => undefined, }; const html = render( `\`\`\`ts const value = ''; \`\`\``, { extensions: [extension] }, ); t.is( removeWhitespaces(html), removeWhitespaces( '
const value = '<safe>';
', ), ); }); test('math extensions', (t) => { const extension: SlimdownExtension = { renderInlineMath: ({ math, escapeHtml }) => `${escapeHtml(math)}`, renderMathBlock: ({ math, escapeHtml }) => `
${escapeHtml(math)}
`, }; const html = render( `Inline $E = mc^2$. $$ \\sum_i x_i $$`, { extensions: [extension] }, ); t.is( removeWhitespaces(html), removeWhitespaces( '

Inline E = mc^2.

\\sum_i x_i
', ), ); }); test('ordered list preserves non-one start number', (t) => { const md = `3. Third item 4. Fourth item`; const expected = `
  1. Third item
  2. Fourth item
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('ordered list continuation after intervening paragraph keeps numbering', (t) => { const md = `1. First item Some text between. 2. Second item`; const expected = `
  1. First item

Some text between.

  1. Second item
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('ordered lists support closing parenthesis markers', (t) => { const md = `1) First item 2) Second item`; const expected = `
  1. First item
  2. Second item
`; const html = render(md); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('alpha lists are ignored by default', (t) => { const md = `a. First item b. Second item`; const html = render(md); t.false(html.includes(' { const md = `a. First item b. Second item`; const expected = `
  1. First item
  2. Second item
`; const html = render(md, { alphaLists: true }); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('single alpha markers are ignored even when alpha lists are enabled', (t) => { const md = `A. Smith wrote this paragraph.`; const html = render(md, { alphaLists: true }); t.false(html.includes(' { const md = `a. First item c. Third item`; const html = render(md, { alphaLists: true }); t.false(html.includes(' { const md = `A. first item 1. first sub item 2. second sub item B. second item`; const expected = `
  1. first item
    1. first sub item
    2. second sub item
  2. second item
`; const html = render(md, { alphaLists: true }); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('uppercase alpha lists preserve style and start', (t) => { const md = `C) Third item D) Fourth item`; const expected = `
  1. Third item
  2. Fourth item
`; const html = render(md, { alphaLists: true }); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('parenthesized alpha list markers are supported', (t) => { const md = `(b) Second item (c) Third item`; const expected = `
  1. Second item
  2. Third item
`; const html = render(md, { alphaLists: true }); t.is(removeWhitespaces(html), removeWhitespaces(expected)); }); test('code block with language class', (t) => { const md = "```js\nconsole.log('hi');\n```\n"; const html = render(md); t.true(html.includes('')); t.true(html.includes('console.log('hi');')); }); test('code block without language has no class', (t) => { const md = "```\nplain code\n```\n"; const html = render(md); t.true(html.includes('plain code')); }); test('hard line breaks', (t) => { const md = 'first line \nsecond line'; const html = render(md, true); t.true(html.includes('
')); t.true(html.includes('second line')); }); test('autolinks', (t) => { const html = render('', true); t.is(removeWhitespaces(html), removeWhitespaces('https://example.com')); }); test('render with RenderOptions object', (t) => { const md = 'Hello [link](https://example.com)'; const html = render(md, { removeParagraphs: true, externalLinks: true }); t.true(html.includes('target="_blank"')); t.false(html.includes('

')); });