var test = require('tape') var micromark = require('micromark/lib') var voids = require('html-void-elements') var syntax = require('.') var html = require('./html') test('micromark-extension-directive (syntax)', function (t) { t.test('text', function (t) { t.equal( micromark('\\:a', options()), '<p>:a</p>', 'should support an escaped colon which would otherwise be a directive' ) t.equal( micromark('\\::a', options()), '<p>:</p>', 'should support a directive after an escaped colon' ) t.equal( micromark('a ::b', options()), '<p>a ::b</p>', 'should not support a directive after a colon' ) t.equal( micromark(':', options()), '<p>:</p>', 'should not support a colon not followed by an alpha' ) t.equal( micromark(':a', options()), '<p></p>', 'should support a colon followed by an alpha' ) t.equal( micromark(':9', options()), '<p>:9</p>', 'should not support a colon followed by a digit' ) t.equal( micromark(':-', options()), '<p>:-</p>', 'should not support a colon followed by a dash' ) t.equal( micromark(':a9', options()), '<p></p>', 'should support a digit in a name' ) t.equal( micromark(':a-', options()), '<p></p>', 'should support a dash in a name' ) t.equal( micromark(':a[', options()), '<p>[</p>', 'should support a name followed by an unclosed `[`' ) t.equal( micromark(':a{', options()), '<p>{</p>', 'should support a name followed by an unclosed `{`' ) t.equal( micromark(':a[b', options()), '<p>[b</p>', 'should support a name followed by an unclosed `[` w/ content' ) t.equal( micromark(':a{b', options()), '<p>{b</p>', 'should support a name followed by an unclosed `{` w/ content' ) t.equal( micromark(':a[]', options()), '<p></p>', 'should support an empty label' ) t.equal( micromark(':a[ \t]', options()), '<p></p>', 'should support a whitespace only label' ) t.equal( micromark(':a[\n]', options()), '<p></p>', 'should support an eol in an label' ) t.equal( micromark(':a[a b c]asd', options()), '<p>asd</p>', 'should support content in an label' ) t.equal( micromark(':a[a *b* c]asd', options()), '<p>asd</p>', 'should support markdown in an label' ) t.equal( micromark('a :b[c :d[e] f] g', options()), '<p>a g</p>', 'should support a directive in an label' ) t.equal( micromark(':a[]asd', options()), '<p>asd</p>', 'should support content after a label' ) t.equal( micromark(':a{}', options()), '<p></p>', 'should support empty attributes' ) t.equal( micromark(':a{ \t}', options()), '<p></p>', 'should support whitespace only attributes' ) t.equal( micromark(':a{\n}', options()), '<p></p>', 'should support an eol in attributes' ) t.equal( micromark(':a{a b c}', options()), '<p></p>', 'should support attributes w/o values' ) t.equal( micromark(':a{a=b c=d}', options()), '<p></p>', 'should support attributes w/ unquoted values' ) t.equal( micromark(':a{.a .b}', options()), '<p></p>', 'should support attributes w/ class shortcut' ) t.equal( micromark(':a{.a.b}', options()), '<p></p>', 'should support attributes w/ class shortcut w/o whitespace between' ) t.equal( micromark(':a{#a #b}', options()), '<p></p>', 'should support attributes w/ id shortcut' ) t.equal( micromark(':a{#a#b}', options()), '<p></p>', 'should support attributes w/ id shortcut w/o whitespace between' ) t.equal( micromark(':a{#a.b.c#d e f=g #h.i.j}', options()), '<p></p>', 'should support attributes w/ shortcuts combined w/ other attributes' ) t.equal( micromark(':a{..b}', options()), '<p>{..b}</p>', 'should not support an empty shortcut (`.`)' ) t.equal( micromark(':a{.#b}', options()), '<p>{.#b}</p>', 'should not support an empty shortcut (`#`)' ) t.equal( micromark(':a{.}', options()), '<p>{.}</p>', 'should not support an empty shortcut (`}`)' ) t.equal( micromark(':a{.a=b}', options()), '<p>{.a=b}</p>', 'should not support certain characters in shortcuts (`=`)' ) t.equal( micromark(':a{.a"b}', options()), '<p>{.a"b}</p>', 'should not support certain characters in shortcuts (`"`)' ) t.equal( micromark(':a{.a<b}', options()), '<p>{.a<b}</p>', 'should not support certain characters in shortcuts (`<`)' ) t.equal( micromark(':a{.a💚b}', options()), '<p></p>', 'should support most characters in shortcuts' ) t.equal( micromark(':a{_}', options()), '<p></p>', 'should support an underscore in attribute names' ) t.equal( micromark(':a{xml:lang}', options()), '<p></p>', 'should support a colon in attribute names' ) t.equal( micromark(':a{a="b" c="d e f"}', options()), '<p></p>', 'should support double quoted attributes' ) t.equal( micromark(":a{a='b' c='d e f'}", options()), '<p></p>', 'should support single quoted attributes' ) t.equal( micromark(':a{a = b c\t=\t\'d\' f =\r"g"}', options()), '<p></p>', 'should support whitespace around initializers' ) t.equal( micromark(':a{b==}', options()), '<p>{b==}</p>', 'should not support `=` to start an unquoted attribute value' ) t.equal( micromark(':a{b=}', options()), '<p>{b=}</p>', 'should not support a missing attribute value after `=`' ) t.equal( micromark(":a{b=c'}", options()), "<p>{b=c'}</p>", 'should not support an apostrophe in an unquoted attribute value' ) t.equal( micromark(':a{b=c`}', options()), '<p>{b=c`}</p>', 'should not support a grave accent in an unquoted attribute value' ) t.equal( micromark(':a{b=a💚b}', options()), '<p></p>', 'should support most other characters in unquoted attribute values' ) t.equal( micromark(':a{b="c', options()), '<p>{b="c</p>', 'should not support an EOF in a quoted attribute value' ) t.equal( micromark(':a{b="a💚b"}', options()), '<p></p>', 'should support most other characters in quoted attribute values' ) t.equal( micromark(':a{b="\nc\r d"}', options()), '<p></p>', 'should support EOLs in quoted attribute values' ) t.equal( micromark(':a{b="c"', options()), '<p>{b="c"</p>', 'should not support an EOF after a quoted attribute value' ) t.end() }) t.test('leaf', function (t) { t.equal(micromark('::b', options()), '', 'should support a directive') t.equal( micromark(':', options()), '<p>:</p>', 'should not support one colon' ) t.equal( micromark('::', options()), '<p>::</p>', 'should not support two colons not followed by an alpha' ) t.equal( micromark('::a', options()), '', 'should support two colons followed by an alpha' ) t.equal( micromark('::9', options()), '<p>::9</p>', 'should not support two colons followed by a digit' ) t.equal( micromark('::-', options()), '<p>::-</p>', 'should not support two colons followed by a dash' ) t.equal( micromark('::a9', options()), '', 'should support a digit in a name' ) t.equal(micromark('::a-', options()), '', 'should support a dash in a name') t.equal( micromark('::a[', options()), '<p>::a[</p>', 'should not support a name followed by an unclosed `[`' ) t.equal( micromark('::a{', options()), '<p>::a{</p>', 'should not support a name followed by an unclosed `{`' ) t.equal( micromark('::a[b', options()), '<p>::a[b</p>', 'should not support a name followed by an unclosed `[` w/ content' ) t.equal( micromark('::a{b', options()), '<p>::a{b</p>', 'should not support a name followed by an unclosed `{` w/ content' ) t.equal(micromark('::a[]', options()), '', 'should support an empty label') t.equal( micromark('::a[ \t]', options()), '', 'should support a whitespace only label' ) t.equal( micromark('::a[\n]', options()), '<p>::a[\n]</p>', 'should not support an eol in an label' ) t.equal( micromark('::a[a b c]', options()), '', 'should support content in an label' ) t.equal( micromark('::a[a *b* c]', options()), '', 'should support markdown in an label' ) t.equal( micromark('::a[]asd', options()), '<p>::a[]asd</p>', 'should not support content after a label' ) t.equal( micromark('::a{}', options()), '', 'should support empty attributes' ) t.equal( micromark('::a{ \t}', options()), '', 'should support whitespace only attributes' ) t.equal( micromark('::a{\n}', options()), '<p>::a{\n}</p>', 'should not support an eol in attributes' ) t.equal( micromark('::a{a b c}', options()), '', 'should support attributes w/o values' ) t.equal( micromark('::a{a=b c=d}', options()), '', 'should support attributes w/ unquoted values' ) t.equal( micromark('::a{.a .b}', options()), '', 'should support attributes w/ class shortcut' ) t.equal( micromark('::a{#a #b}', options()), '', 'should support attributes w/ id shortcut' ) t.equal( micromark('::a{.a💚b}', options()), '', 'should support most characters in shortcuts' ) t.equal( micromark('::a{a="b" c="d e f"}', options()), '', 'should support double quoted attributes' ) t.equal( micromark("::a{a='b' c='d e f'}", options()), '', 'should support single quoted attributes' ) t.equal( micromark("::a{a = b c\t=\t'd'}", options()), '', 'should support whitespace around initializers' ) t.equal( micromark('::a{f =\rg}', options()), '<p>::a{f =\rg}</p>', 'should not support EOLs around initializers' ) t.equal( micromark('::a{b==}', options()), '<p>::a{b==}</p>', 'should not support `=` to start an unquoted attribute value' ) t.equal( micromark('::a{b=a💚b}', options()), '', 'should support most other characters in unquoted attribute values' ) t.equal( micromark('::a{b="c', options()), '<p>::a{b="c</p>', 'should not support an EOF in a quoted attribute value' ) t.equal( micromark('::a{b="a💚b"}', options()), '', 'should support most other characters in quoted attribute values' ) t.equal( micromark('::a{b="\nc\r d"}', options()), '<p>::a{b="\nc\rd"}</p>', 'should not support EOLs in quoted attribute values' ) t.equal( micromark('::a{b="c"', options()), '<p>::a{b="c"</p>', 'should not support an EOF after a quoted attribute value' ) t.equal( micromark('::a{b=c} \t ', options()), '', 'should support whitespace after directives' ) t.equal( micromark('::a{b=c}\n>a', options()), '<blockquote>\n<p>a</p>\n</blockquote>', 'should support a block quote after a leaf' ) t.equal( micromark('::a{b=c}\n```js\na', options()), '<pre><code class="language-js">a\n</code></pre>\n', 'should support code (fenced) after a leaf' ) t.equal( micromark('::a{b=c}\n a', options()), '<pre><code>a\n</code></pre>', 'should support code (indented) after a leaf' ) t.equal( micromark('::a{b=c}\n[a]: b', options()), '', 'should support a definition after a leaf' ) t.equal( micromark('::a{b=c}\n# a', options()), '<h1>a</h1>', 'should support a heading (atx) after a leaf' ) t.equal( micromark('::a{b=c}\na\n=', options()), '<h1>a</h1>', 'should support a heading (setext) after a leaf' ) t.equal( micromark('::a{b=c}\n<!-->', options()), '<!-->', 'should support html after a leaf' ) t.equal( micromark('::a{b=c}\n* a', options()), '<ul>\n<li>a</li>\n</ul>', 'should support a list after a leaf' ) t.equal( micromark('::a{b=c}\na', options()), '<p>a</p>', 'should support a paragraph after a leaf' ) t.equal( micromark('::a{b=c}\n***', options()), '<hr />', 'should support a thematic break after a leaf' ) t.equal( micromark('>a\n::a{b=c}', options()), '<blockquote>\n<p>a</p>\n</blockquote>\n', 'should support a block quote before a leaf' ) t.equal( micromark('```js\na\n```\n::a{b=c}', options()), '<pre><code class="language-js">a\n</code></pre>\n', 'should support code (fenced) before a leaf' ) t.equal( micromark(' a\n::a{b=c}', options()), '<pre><code>a\n</code></pre>\n', 'should support code (indented) before a leaf' ) t.equal( micromark('[a]: b\n::a{b=c}', options()), '', 'should support a definition before a leaf' ) t.equal( micromark('# a\n::a{b=c}', options()), '<h1>a</h1>\n', 'should support a heading (atx) before a leaf' ) t.equal( micromark('a\n=\n::a{b=c}', options()), '<h1>a</h1>\n', 'should support a heading (setext) before a leaf' ) t.equal( micromark('<!-->\n::a{b=c}', options()), '<!-->\n', 'should support html before a leaf' ) t.equal( micromark('* a\n::a{b=c}', options()), '<ul>\n<li>a</li>\n</ul>\n', 'should support a list before a leaf' ) t.equal( micromark('a\n::a{b=c}', options()), '<p>a</p>\n', 'should support a paragraph before a leaf' ) t.equal( micromark('***\n::a{b=c}', options()), '<hr />\n', 'should support a thematic break before a leaf' ) t.end() }) t.test('container', function (t) { t.equal(micromark(':::b', options()), '', 'should support a directive') t.equal( micromark(':', options()), '<p>:</p>', 'should not support one colon' ) t.equal( micromark('::', options()), '<p>::</p>', 'should not support two colons not followed by an alpha' ) t.equal( micromark(':::', options()), '<p>:::</p>', 'should not support three colons not followed by an alpha' ) t.equal( micromark(':::a', options()), '', 'should support three colons followed by an alpha' ) t.equal( micromark(':::9', options()), '<p>:::9</p>', 'should not support three colons followed by a digit' ) t.equal( micromark(':::-', options()), '<p>:::-</p>', 'should not support three colons followed by a dash' ) t.equal( micromark(':::a9', options()), '', 'should support a digit in a name' ) t.equal( micromark(':::a-', options()), '', 'should support a dash in a name' ) t.equal( micromark(':::a[', options()), '<p>:::a[</p>', 'should not support a name followed by an unclosed `[`' ) t.equal( micromark(':::a{', options()), '<p>:::a{</p>', 'should not support a name followed by an unclosed `{`' ) t.equal( micromark(':::a[b', options()), '<p>:::a[b</p>', 'should not support a name followed by an unclosed `[` w/ content' ) t.equal( micromark(':::a{b', options()), '<p>:::a{b</p>', 'should not support a name followed by an unclosed `{` w/ content' ) t.equal(micromark(':::a[]', options()), '', 'should support an empty label') t.equal( micromark(':::a[ \t]', options()), '', 'should support a whitespace only label' ) t.equal( micromark(':::a[\n]', options()), '<p>:::a[\n]</p>', 'should not support an eol in an label' ) t.equal( micromark(':::a[a b c]', options()), '', 'should support content in an label' ) t.equal( micromark(':::a[a *b* c]', options()), '', 'should support markdown in an label' ) t.equal( micromark(':::a[]asd', options()), '<p>:::a[]asd</p>', 'should not support content after a label' ) t.equal( micromark(':::a{}', options()), '', 'should support empty attributes' ) t.equal( micromark(':::a{ \t}', options()), '', 'should support whitespace only attributes' ) t.equal( micromark(':::a{\n}', options()), '<p>:::a{\n}</p>', 'should not support an eol in attributes' ) t.equal( micromark(':::a{a b c}', options()), '', 'should support attributes' ) t.equal( micromark(':::a{f =\rg}', options()), '<p>:::a{f =\rg}</p>', 'should not support EOLs around initializers' ) t.equal( micromark(':::a{b="c', options()), '<p>:::a{b="c</p>', 'should not support an EOF in a quoted attribute value' ) t.equal( micromark(':::a{b="\nc\r d"}', options()), '<p>:::a{b="\nc\rd"}</p>', 'should not support EOLs in quoted attribute values' ) t.equal( micromark(':::a{b="c"', options()), '<p>:::a{b="c"</p>', 'should not support an EOF after a quoted attribute value' ) t.equal( micromark(':::a{b=c} \t ', options()), '', 'should support whitespace after directives' ) t.equal( micromark(':::a\n', options()), '', 'should support no closing fence' ) t.equal( micromark(':::a\n:::', options()), '', 'should support an immediate closing fence' ) t.equal( micromark(':::a\n:::\nb', options()), '<p>b</p>', 'should support content after a closing fence' ) t.equal( micromark(':::a\n::\nb', options()), '', 'should not close w/ a “closing” fence of two colons' ) t.equal( micromark(':::a\n::::\nb', options()), '<p>b</p>', 'should close w/ a closing fence of more colons' ) t.equal( micromark('::::a\n::::\nb', options()), '<p>b</p>', 'should support more opening colons' ) t.equal( micromark(':::::a\n::::\nb', options()), '', 'should not close w/ a “closing” fence of less colons than the opening' ) t.equal( micromark(':::a\n::: \t\nc', options()), '<p>c</p>', 'should close w/ a closing fence followed by white space' ) t.equal( micromark(':::a\n::: b\nc', options()), '', 'should not close w/ a “closing” fence followed by other characters' ) t.equal( micromark(':::a\n :::\nc', options()), '<p>c</p>', 'should close w/ an indented closing fence' ) t.equal( micromark(':::a\n\t:::\nc', options()), '', 'should not close w/ when the “closing” fence is indented at a tab size' ) t.equal( micromark(':::a\n :::\nc', options()), '', 'should not close w/ when the “closing” fence is indented more than a tab size' ) t.equal( micromark(':::a\n\n \n\ta', options()), '', 'should support blank lines in content' ) t.equal( micromark(':::a\n\ta\n', options()), '', 'should support an EOL EOF' ) t.equal( micromark(' :::a\n b\n :::\nc', options()), '<p>c</p>', 'should support an indented directive' ) t.equal( micromark(' :::a\n\t:::\nc', options()), '', 'should still not close an indented directive when the “closing” fence is indented a tab size' ) t.equal( micromark(':::a\n:::\n>a', options()), '<blockquote>\n<p>a</p>\n</blockquote>', 'should support a block quote after a container' ) t.equal( micromark(':::a\n:::\n```js\na', options()), '<pre><code class="language-js">a\n</code></pre>\n', 'should support code (fenced) after a container' ) t.equal( micromark(':::a\n:::\n a', options()), '<pre><code>a\n</code></pre>', 'should support code (indented) after a container' ) t.equal( micromark(':::a\n:::\n[a]: b', options()), '', 'should support a definition after a container' ) t.equal( micromark(':::a\n:::\n# a', options()), '<h1>a</h1>', 'should support a heading (atx) after a container' ) t.equal( micromark(':::a\n:::\na\n=', options()), '<h1>a</h1>', 'should support a heading (setext) after a container' ) t.equal( micromark(':::a\n:::\n<!-->', options()), '<!-->', 'should support html after a container' ) t.equal( micromark(':::a\n:::\n* a', options()), '<ul>\n<li>a</li>\n</ul>', 'should support a list after a container' ) t.equal( micromark(':::a\n:::\na', options()), '<p>a</p>', 'should support a paragraph after a container' ) t.equal( micromark(':::a\n:::\n***', options()), '<hr />', 'should support a thematic break after a container' ) t.equal( micromark('>a\n:::a\nb', options()), '<blockquote>\n<p>a</p>\n</blockquote>\n', 'should support a block quote before a container' ) t.equal( micromark('```js\na\n```\n:::a\nb', options()), '<pre><code class="language-js">a\n</code></pre>\n', 'should support code (fenced) before a container' ) t.equal( micromark(' a\n:::a\nb', options()), '<pre><code>a\n</code></pre>\n', 'should support code (indented) before a container' ) t.equal( micromark('[a]: b\n:::a\nb', options()), '', 'should support a definition before a container' ) t.equal( micromark('# a\n:::a\nb', options()), '<h1>a</h1>\n', 'should support a heading (atx) before a container' ) t.equal( micromark('a\n=\n:::a\nb', options()), '<h1>a</h1>\n', 'should support a heading (setext) before a container' ) t.equal( micromark('<!-->\n:::a\nb', options()), '<!-->\n', 'should support html before a container' ) t.equal( micromark('* a\n:::a\nb', options()), '<ul>\n<li>a</li>\n</ul>\n', 'should support a list before a container' ) t.equal( micromark('a\n:::a\nb', options()), '<p>a</p>\n', 'should support a paragraph before a container' ) t.equal( micromark('***\n:::a\nb', options()), '<hr />\n', 'should support a thematic break before a container' ) t.equal( micromark(' :::x\n ', options({'*': h})), '<x></x>', 'should support prefixed containers (1)' ) t.equal( micromark(' :::x\n - a', options({'*': h})), '<x>\n<ul>\n<li>a</li>\n</ul>\n</x>', 'should support prefixed containers (2)' ) t.equal( micromark(' :::x\n - a\n > b', options({'*': h})), '<x>\n<ul>\n<li>a</li>\n</ul>\n<blockquote>\n<p>b</p>\n</blockquote>\n</x>', 'should support prefixed containers (3)' ) t.equal( micromark(' :::x\n - a\n > b\n :::', options({'*': h})), '<x>\n<ul>\n<li>a</li>\n</ul>\n<blockquote>\n<p>b</p>\n</blockquote>\n</x>', 'should support prefixed containers (4)' ) t.end() }) t.end() }) test('micromark-extension-directive (compile)', function (t) { t.equal( micromark( [ ':abbr', ':abbr[HTML]', ':abbr{title="HyperText Markup Language"}', ':abbr[HTML]{title="HyperText Markup Language"}' ].join('\n\n'), options({abbr: abbr}) ), [ '<p><abbr></abbr></p>', '<p><abbr>HTML</abbr></p>', '<p><abbr title="HyperText Markup Language"></abbr></p>', '<p><abbr title="HyperText Markup Language">HTML</abbr></p>' ].join('\n'), 'should support a directives (abbr)' ) t.equal( micromark( [ 'Text:', ':youtube', ':youtube[Cat in a box a]', ':youtube{v=1}', ':youtube[Cat in a box b]{v=2}', 'Leaf:', '::youtube', '::youtube[Cat in a box c]', '::youtube{v=3}', '::youtube[Cat in a box d]{v=4}', 'Container:', ':::youtube\nw\n:::', ':::youtube[Cat in a box e]\nx\n:::', ':::youtube{v=5}\ny\n:::', ':::youtube[Cat in a box f]{v=6}\nz\n:::' ].join('\n\n'), options({youtube: youtube}) ), [ '<p>Text:</p>', '<p></p>', '<p></p>', '<p><iframe src="https://www.youtube.com/embed/1" allowfullscreen></iframe></p>', '<p><iframe src="https://www.youtube.com/embed/2" allowfullscreen title="Cat in a box b"></iframe></p>', '<p>Leaf:</p>', '<iframe src="https://www.youtube.com/embed/3" allowfullscreen></iframe>', '<iframe src="https://www.youtube.com/embed/4" allowfullscreen title="Cat in a box d"></iframe>', '<p>Container:</p>', '<iframe src="https://www.youtube.com/embed/5" allowfullscreen>', '<p>y</p>', '</iframe>', '<iframe src="https://www.youtube.com/embed/6" allowfullscreen title="Cat in a box f">', '<p>z</p>', '</iframe>' ].join('\n'), 'should support directives (youtube)' ) t.equal( micromark( ':youtube[Cat in a box]\n:br', options({youtube: youtube, '*': h}) ), '<p><youtube>Cat in a box</youtube>\n<br></p>', 'should support fall through directives (`*`)' ) t.equal( micromark(':a[:img{src="x" alt=y}]{href="z"}', options({'*': h})), '<p><a href="z"><img src="x" alt="y"></a></p>', 'should support fall through directives (`*`)' ) t.end() }) test('content', function (t) { t.equal( micromark(':abbr[x\\&y&z]', options({abbr: abbr})), '<p><abbr>x&y&z</abbr></p>', 'should support character escapes and character references in label' ) t.equal( micromark(':abbr[x\\[y\\]z]', options({abbr: abbr})), '<p><abbr>x[y]z</abbr></p>', 'should support escaped brackets in a label' ) t.equal( micromark(':abbr[x[y]z]', options({abbr: abbr})), '<p><abbr>x[y]z</abbr></p>', 'should support balanced brackets in a label' ) t.equal( micromark(':abbr[a[b[c[d]e]f]g]h', options({abbr: abbr})), '<p><abbr>a[b[c[d]e]f]g</abbr>h</p>', 'should support balanced brackets in a label, three levels deep' ) t.equal( micromark(':abbr[a[b[c[d[e]f]g]h]i]j', options({abbr: abbr})), '<p><abbr></abbr>[a[b[c[d[e]f]g]h]i]j</p>', 'should *not* support balanced brackets in a label, four levels deep' ) t.equal( micromark(':abbr[a\nb\rc]', options({abbr: abbr})), '<p><abbr>a\nb\rc</abbr></p>', 'should support EOLs in a label' ) t.equal( micromark(':abbr[\na\r]', options({abbr: abbr})), '<p><abbr>\na\r</abbr></p>', 'should support EOLs at the edges of a label' ) t.equal( micromark(':abbr[a *b* **c** d]', options({abbr: abbr})), '<p><abbr>a <em>b</em> <strong>c</strong> d</abbr></p>', 'should support markdown in a label' ) t.equal( micromark(':abbr{title=a'b}', options({abbr: abbr})), '<p><abbr title="a\'b"></abbr></p>', 'should support character references in unquoted attribute values' ) t.equal( micromark(':abbr{title="a'b"}', options({abbr: abbr})), '<p><abbr title="a\'b"></abbr></p>', 'should support character references in double attribute values' ) t.equal( micromark(":abbr{title='a'b'}", options({abbr: abbr})), '<p><abbr title="a\'b"></abbr></p>', 'should support character references in single attribute values' ) t.equal( micromark(':abbr{title="a&somethingelse;b"}', options({abbr: abbr})), '<p><abbr title="a&somethingelse;b"></abbr></p>', 'should support unknown character references in attribute values' ) t.equal( micromark(':span{a\nb}', options({'*': h})), '<p><span a="" b=""></span></p>', 'should support EOLs between attributes' ) t.equal( micromark(':span{\na\n}', options({'*': h})), '<p><span a=""></span></p>', 'should support EOLs at the edges of attributes' ) t.equal( micromark(':span{a\r= b}', options({'*': h})), '<p><span a="b"></span></p>', 'should support EOLs before initializer' ) t.equal( micromark(':span{a=\r\nb}', options({'*': h})), '<p><span a="b"></span></p>', 'should support EOLs after initializer' ) t.equal( micromark(':span{a=b\nc}', options({'*': h})), '<p><span a="b" c=""></span></p>', 'should support EOLs between an unquoted attribute value and a next attribute name' ) t.equal( micromark(':span{a="b\nc"}', options({'*': h})), '<p><span a="b\nc"></span></p>', 'should support EOLs in a double quoted attribute value' ) t.equal( micromark(":span{a='b\nc'}", options({'*': h})), '<p><span a="b\nc"></span></p>', 'should support EOLs in a single quoted attribute value' ) t.equal( micromark(':span{#a#b}', options({'*': h})), '<p><span id="b"></span></p>', 'should support `id` shortcuts' ) t.equal( micromark(':span{id=a id="b" #c#d}', options({'*': h})), '<p><span id="d"></span></p>', 'should support `id` shortcuts after `id` attributes' ) t.equal( micromark(':span{.a.b}', options({'*': h})), '<p><span class="a b"></span></p>', 'should support `class` shortcuts' ) t.equal( micromark(':span{class=a class="b c" .d.e}', options({'*': h})), '<p><span class="a b c d e"></span></p>', 'should support `class` shortcuts after `class` attributes' ) t.equal( micromark('::::div{.big}\n:::div{.small}\nText', options({'*': h})), '<div class="big">\n<div class="small">\n<p>Text</p>\n</div>\n</div>', 'should support container directives in container directives' ) t.equal( micromark(':::div{.big}\n::hr{.small}', options({'*': h})), '<div class="big">\n<hr class="small">\n</div>', 'should support leaf directives in container directives' ) t.equal( micromark(':::div{.big}\n:b[Text]', options({'*': h})), '<div class="big">\n<p><b>Text</b></p>\n</div>', 'should support text directives in container directives' ) t.equal( micromark(':::section\n* a\n:::', options({'*': h})), '<section>\n<ul>\n<li>a</li>\n</ul>\n</section>', 'should support lists in container directives' ) t.equal( micromark(':::section[]\n* a\n:::', options({'*': h})), '<section>\n<ul>\n<li>a</li>\n</ul>\n</section>', 'should support lists w/ label brackets in container directives' ) t.equal( micromark(':::section{}\n* a\n:::', options({'*': h})), '<section>\n<ul>\n<li>a</li>\n</ul>\n</section>', 'should support lists w/ attribute braces in container directives' ) t.end() }) function abbr(d) { if (d.type !== 'textDirective') return false this.tag('<abbr') if (d.attributes && 'title' in d.attributes) { this.tag(' title="' + this.encode(d.attributes.title) + '"') } this.tag('>') this.raw(d.label || '') this.tag('</abbr>') } function youtube(d) { var attrs = d.attributes || {} var v = attrs.v var list var prop if (!v) return false list = [ 'src="https://www.youtube.com/embed/' + this.encode(v) + '"', 'allowfullscreen' ] if (d.label) { list.push('title="' + this.encode(d.label) + '"') } for (prop in attrs) { if (prop !== 'v') { list.push(this.encode(prop) + '="' + this.encode(attrs[prop]) + '"') } } this.tag('<iframe ' + list.join(' ') + '>') if (d.content) { this.lineEndingIfNeeded() this.raw(d.content) this.lineEndingIfNeeded() } this.tag('</iframe>') } function h(d) { var content = d.content || d.label var attrs = d.attributes || {} var list = [] var prop for (prop in attrs) { list.push(this.encode(prop) + '="' + this.encode(attrs[prop]) + '"') } this.tag('<' + d.name) if (list.length) this.tag(' ' + list.join(' ')) this.tag('>') if (content) { if (d.type === 'containerDirective') this.lineEndingIfNeeded() this.raw(content) if (d.type === 'containerDirective') this.lineEndingIfNeeded() } if (!voids.includes(d.name)) this.tag('</' + d.name + '>') } function options(options) { return { allowDangerousHtml: true, extensions: [syntax()], htmlExtensions: [html(options)] } }