import { assert } from 'chai'; import markdownit from '../index.mjs'; import forInline from 'markdown-it-for-inline'; describe('API', function () { it('constructor', function () { assert.throws(function () { markdownit('bad preset'); }); // options should override preset var md = markdownit('commonmark', { html: false }); assert.strictEqual(md.render(''), '
<!-- -->
\n'); }); it('configure coverage', function () { var md = markdownit(); // conditions coverage md.configure({}); assert.strictEqual(md.render('123'), '123
\n'); assert.throws(function () { md.configure(); }); }); it('plugin', function () { var succeeded = false; function plugin(slf, opts) { if (opts === 'bar') { succeeded = true; } } var md = markdownit(); md.use(plugin, 'foo'); assert.strictEqual(succeeded, false); md.use(plugin, 'bar'); assert.strictEqual(succeeded, true); }); it('highlight', function () { var md = markdownit({ highlight: function (str) { return '==' + str + '==
';
}
});
assert.strictEqual(md.render('```\nhl\n```'), '==hl\n==
\n');
});
it('highlight escape by default', function () {
var md = markdownit({
highlight: function () {
return '';
}
});
assert.strictEqual(md.render('```\n&\n```'), '&\n
\n');
});
it('highlight arguments', function () {
var md = markdownit({
highlight: function (str, lang, attrs) {
assert.strictEqual(lang, 'a');
assert.strictEqual(attrs, 'b c d');
return '==' + str + '==
';
}
});
assert.strictEqual(md.render('``` a b c d \nhl\n```'), '==hl\n==
\n');
});
it('force hardbreaks', function () {
var md = markdownit({ breaks: true });
assert.strictEqual(md.render('a\nb'), 'a
\nb
a
\nb
a
\nb
a
\nb
foo\uFFFDbar
\n'); }); it('Should correctly parse strings without tailing \\n', function () { var md = markdownit(); assert.strictEqual(md.render('123'), '123
\n'); assert.strictEqual(md.render('123\n'), '123
\n'); assert.strictEqual(md.render(' codeblock'), 'codeblock\n
\n');
assert.strictEqual(md.render(' codeblock\n'), 'codeblock\n
\n');
});
it('Should quickly exit on empty string', function () {
var md = markdownit();
assert.strictEqual(md.render(''), '');
});
it('Should parse inlines only', function () {
var md = markdownit();
assert.strictEqual(md.renderInline('a *b* c'), 'a b c');
});
it('Renderer should have pluggable inline and block rules', function () {
var md = markdownit();
md.renderer.rules.em_open = function () { return '___foo___
\n'); assert.strictEqual(md.renderInline('___foo___'), '___foo___'); md.enable('emphasis'); assert.strictEqual(md.render('___foo___'), 'foo
\n'); assert.strictEqual(md.renderInline('___foo___'), 'foo'); }); it('Should correctly check block termination rules when those are disabled (#13)', function () { var md = markdownit('zero'); assert.strictEqual(md.render('foo\nbar'), 'foo\nbar
\n'); }); it('Should render link target attr', function () { var md = markdownit() .use(forInline, 'target', 'link_open', function (tokens, idx) { tokens[idx].attrs.push([ 'target', '_blank' ]); }); assert.strictEqual(md.render('[foo](bar)'), '\n'); }); it('Should normalize CR to LF', function () { var md = markdownit(); assert.strictEqual( md.render('# test\r\r - hello\r - world\r'), md.render('# test\n\n - hello\n - world\n') ); }); it('Should normalize CR+LF to LF', function () { var md = markdownit(); assert.strictEqual( md.render('# test\r\n\r\n - hello\r\n - world\r\n'), md.render('# test\n\n - hello\n - world\n') ); }); it('Should escape surrogate pairs (coverage)', function () { var md = markdownit(); assert.strictEqual(md.render('\\\uD835\uDC9C'), '\\\uD835\uDC9C
\n'); assert.strictEqual(md.render('\\\uD835x'), '\\\uD835x
\n'); assert.strictEqual(md.render('\\\uD835'), '\\\uD835
\n'); }); }); describe('Url normalization', function () { it('Should be overridable', function () { var md = markdownit({ linkify: true }); md.normalizeLink = function (url) { assert(url.match(/example\.com/), 'wrong url passed'); return 'LINK'; }; md.normalizeLinkText = function (url) { assert(url.match(/example\.com/), 'wrong url passed'); return 'TEXT'; }; assert.strictEqual(md.render('foo@example.com'), '\n'); assert.strictEqual(md.render('http://example.com'), '\n'); assert.strictEqual(md.render('foo@example.com
\n'); assert.strictEqual(md.render('http://example.com'), 'http://example.com
\n'); assert.strictEqual(md.render('<foo@example.com>
\n'); assert.strictEqual(md.render('<http://example.com>
\n'); assert.strictEqual(md.render('[test](http://example.com)'), '[test](http://example.com)
\n'); assert.strictEqual(md.render('![test](http://example.com)'), '![test](http://example.com)
\n'); }); }); describe('maxNesting', function () { it('Block parser should not nest above limit', function () { var md = markdownit({ maxNesting: 2 }); assert.strictEqual( md.render('>foo\n>>bar\n>>>baz'), '\n\n' ); }); it('Inline parser should not nest above limit', function () { var md = markdownit({ maxNesting: 1 }); assert.strictEqual( md.render('[`foo`]()'), '\n' ); }); it('Inline nesting coverage', function () { var md = markdownit({ maxNesting: 2 }); assert.strictEqual( md.render('[[[[[[[[[[[[[[[[[[foo]()'), 'foo
\n\n
[[[[[[[[[[[[[[[[[[foo]()
\n' ); }); }); describe('smartquotes', function () { var md = markdownit({ typographer: true, // all strings have different length to make sure // we didn't accidentally count the wrong one quotes: [ '[[[', ']]', '(((((', '))))' ] }); it('Should support multi-character quotes', function () { assert.strictEqual( md.render('"foo" \'bar\''), '[[[foo]] (((((bar))))
\n' ); }); it('Should support nested multi-character quotes', function () { assert.strictEqual( md.render('"foo \'bar\' baz"'), '[[[foo (((((bar)))) baz]]
\n' ); }); it('Should support multi-character quotes in different tags', function () { assert.strictEqual( md.render('"a *b \'c *d* e\' f* g"'), '[[[a b (((((c d e)))) f g]]
\n' ); }); }); describe('Ordered list info', function () { var md = markdownit(); function type_filter(tokens, type) { return tokens.filter(function (t) { return t.type === type; }); } it('Should mark ordered list item tokens with info', function () { var tokens = md.parse('1. Foo\n2. Bar\n20. Fuzz'); assert.strictEqual(type_filter(tokens, 'ordered_list_open').length, 1); tokens = type_filter(tokens, 'list_item_open'); assert.strictEqual(tokens.length, 3); assert.strictEqual(tokens[0].info, '1'); assert.strictEqual(tokens[0].markup, '.'); assert.strictEqual(tokens[1].info, '2'); assert.strictEqual(tokens[1].markup, '.'); assert.strictEqual(tokens[2].info, '20'); assert.strictEqual(tokens[2].markup, '.'); tokens = md.parse(' 1. Foo\n2. Bar\n 20. Fuzz\n 199. Flp'); assert.strictEqual(type_filter(tokens, 'ordered_list_open').length, 1); tokens = type_filter(tokens, 'list_item_open'); assert.strictEqual(tokens.length, 4); assert.strictEqual(tokens[0].info, '1'); assert.strictEqual(tokens[0].markup, '.'); assert.strictEqual(tokens[1].info, '2'); assert.strictEqual(tokens[1].markup, '.'); assert.strictEqual(tokens[2].info, '20'); assert.strictEqual(tokens[2].markup, '.'); assert.strictEqual(tokens[3].info, '199'); assert.strictEqual(tokens[3].markup, '.'); }); }); describe('Token attributes', function () { it('.attrJoin', function () { var md = markdownit(); var tokens = md.parse('```'), t = tokens[0]; t.attrJoin('class', 'foo'); t.attrJoin('class', 'bar'); assert.strictEqual( md.renderer.render(tokens, md.options), '
\n'
);
});
it('.attrSet', function () {
var md = markdownit();
var tokens = md.parse('```'),
t = tokens[0];
t.attrSet('class', 'foo');
assert.strictEqual(
md.renderer.render(tokens, md.options),
'
\n'
);
t.attrSet('class', 'bar');
assert.strictEqual(
md.renderer.render(tokens, md.options),
'
\n'
);
});
it('.attrGet', function () {
var md = markdownit();
var tokens = md.parse('```'),
t = tokens[0];
assert.strictEqual(t.attrGet('myattr'), null);
t.attrSet('myattr', 'myvalue');
assert.strictEqual(t.attrGet('myattr'), 'myvalue');
});
});