/* eslint-env mocha, es6 */ 'use strict'; const assert = require('assert'); const Md = require('markdown-it'); const implicitFigures = require('markdown-it-implicit-figures'); const katex = require('markdown-it-katex'); const attrs = require('./'); const utils = require('./utils.js'); describeTestsWithOptions({ leftDelimiter: '{', rightDelimiter: '}' }, ''); describeTestsWithOptions({ leftDelimiter: '[', rightDelimiter: ']' }, ' with [ ] delimiters'); describeTestsWithOptions({ leftDelimiter: '[[', rightDelimiter: ']]' }, ' with [[ ]] delimiters'); describe('markdown-it-attrs', () => { let md, src, expected; it('should not throw when getting only allowedAttributes option', () => { md = Md().use(attrs, { allowedAttributes: [/^(class|attr)$/] }); src = 'text {.someclass #someid attr=allowed}'; expected = '
text
\n'; assert.equal(md.render(src), expected); }); }); function describeTestsWithOptions(options, postText) { describe('markdown-it-attrs.utils' + postText, () => { it(replaceDelimiters('should parse {.class ..css-module #id key=val .class.with.dot}', options), () => { const src = '{.red ..mod #head key=val .class.with.dot}'; const expected = [['class', 'red'], ['css-module', 'mod'], ['id', 'head'], ['key', 'val'], ['class', 'class.with.dot']]; const res = utils.getAttrs(replaceDelimiters(src, options), 0, options); assert.deepEqual(res, expected); }); it(replaceDelimiters('should parse attributes with = {attr=/id=1}', options), () => { const src = '{link=/some/page/in/app/id=1}'; const expected = [['link', '/some/page/in/app/id=1']]; const res = utils.getAttrs(replaceDelimiters(src, options), 0, options); assert.deepEqual(res, expected); }); it(replaceDelimiters('should parse attributes whose are ignored the key chars(\\t,\\n,\\f,\\s,/,>,",\',=) eg: {gt>=true slash/=trace i\\td "q\\fnu e\'r\\ny"=}', options), () => { const src = '{gt>=true slash/=trace i\td "q\fu\ne\'r\ny"=}'; const expected = [['gt', 'true'], ['slash', 'trace'], ['id', ''], ['query', '']]; const res = utils.getAttrs(replaceDelimiters(src, options), 0, options); assert.deepEqual(res, expected); }); it(replaceDelimiters('should throw an error while calling `hasDelimiters` with an invalid `where` param', options), () => { assert.throws(() => utils.hasDelimiters(0, options), { name: 'Error', message: /Should be "start", "end" or "only"/ }); assert.throws(() => utils.hasDelimiters('', options), { name: 'Error', message: /Should be "start", "end" or "only"/ }); assert.throws(() => utils.hasDelimiters(null, options), { name: 'Error', message: /Should be "start", "end" or "only"/ }); assert.throws(() => utils.hasDelimiters(undefined, options), { name: 'Error', message: /Should be "start", "end" or "only"/ }); assert.throws(() => utils.hasDelimiters('center', options)('has {#test} delimiters'), { name: 'Error', message: /expected 'start', 'end' or 'only'/ }); }); it('should escape html entities(&,<,>,") eg: TOC', () => { const src = 'TOC'; const expected = '<a href="a&b">TOC</a>'; const res = utils.escapeHtml(src); assert.deepEqual(res, expected); }); it('should keep the origional input which is not contains(&,<,>,") char(s) eg: |a|b|', () => { const src = '|a|b|'; const expected = '|a|b|'; const res = utils.escapeHtml(src); assert.deepEqual(res, expected); }); }); describe('markdown-it-attrs' + postText, () => { let md, src, expected; beforeEach(() => { md = Md().use(attrs, options); }); it(replaceDelimiters('should add attributes when {} in end of last inline', options), () => { src = 'some text {with=attrs}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should not add attributes when it has too many delimiters {{}}', options), () => { src = 'some text {{with=attrs}}'; expected = 'some text {{with=attrs}}
\n'; assert.equal(md.render(replaceDelimiters(src, options)), replaceDelimiters(expected, options)); }); it(replaceDelimiters('should add attributes when {} in last line', options), () => { src = 'some text\n{with=attrs}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add classes with {.class} dot notation', options), () => { src = 'some text {.green}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add css-modules with {..css-module} double dot notation', options), () => { src = 'some text {..green}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add identifiers with {#id} hashtag notation', options), () => { src = 'some text {#section2}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should support classes, css-modules, identifiers and attributes in same {}', options), () => { src = 'some text {attr=lorem .class ..css-module #id}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should support attributes inside " {attr="lorem ipsum"}', options), () => { src = 'some text {attr="lorem ipsum"}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add classes in same class attribute {.c1 .c2} -> class="c1 c2"', options), () => { src = 'some text {.c1 .c2}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add css-modules in same css-modules attribute {..c1 ..c2} -> css-module="c1 c2"', options), () => { src = 'some text {..c1 ..c2}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add nested css-modules {..c1.c2} -> css-module="c1.c2"', options), () => { src = 'some text {..c1.c2}'; expected = 'some text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should support empty inline tokens', options), () => { src = ' 1 | 2 \n --|-- \n a | '; md.render(replaceDelimiters(src, options)); // should not crash / throw error }); it(replaceDelimiters('should add classes to inline elements', options), () => { src = 'paragraph **bold**{.red} asdf'; expected = 'paragraph bold asdf
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should not add classes to inline elements with too many {{}}', options), () => { src = 'paragraph **bold**{{.red}} asdf'; expected = 'paragraph bold{{.red}} asdf
\n'; assert.equal(md.render(replaceDelimiters(src, options)), replaceDelimiters(expected, options)); }); it(replaceDelimiters('should only remove last {}', options), () => { src = '{{.red}'; expected = replaceDelimiters('{
\n', options); assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add classes for list items', options), () => { src = '- item 1{.red}\n- item 2'; expected = 'bla click()
text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should add attributes to ul when below last bullet point', options), () => { src = '- item1\n- item2\n{.red}'; expected = 'text
\n'; const res = md.set({ typographer: true }).render(replaceDelimiters(src, options)); assert.equal(res, expected); }); it(replaceDelimiters('should support code blocks', options), () => { src = '```{.c a=1 #ii}\nfor i in range(10):\n```'; expected = 'for i in range(10):\n\n';
assert.equal(md.render(replaceDelimiters(src, options)), expected);
});
it(replaceDelimiters('should support code blocks with language defined', options), () => {
src = '```python {.c a=1 #ii}\nfor i in range(10):\n```';
expected = 'for i in range(10):\n\n';
assert.equal(md.render(replaceDelimiters(src, options)), expected);
});
it(replaceDelimiters('should support blockquotes', options), () => {
src = '> quote\n{.c}';
expected = '\n\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should support tables', options), () => { src = '| h1 | h2 |\n'; src += '| -- | -- |\n'; src += '| c1 | c1 |\n'; src += '\n'; src += '{.c}'; expected = 'quote
\n
| h1 | \n'; expected += 'h2 | \n'; expected += '
|---|---|
| c1 | \n'; expected += 'c1 | \n'; expected += '
| title | \n'; expected += 'title | \n'; expected += '
|---|---|
| text | \n'; expected += 'text | \n'; expected += '
| text | \n'; expected += 'text | \n'; expected += '
| A | \n'; expected += 'B | \n'; expected += 'C | \n'; expected += 'D | \n'; expected += '
|---|---|---|---|
| 1 | \n'; expected += '11 | \n'; expected += '111 | \n'; expected += '1111 | \n'; expected += '
| 2 | \n'; expected += '22 | \n'; expected += '||
| 3 | \n'; expected += '|||
| A | \n'; expected += '||
|---|---|---|
| 1 | \n'; expected += '||
| 2 | \n'; expected += '||
| 3 | \n'; expected += '||
| A | \n'; expected += 'B | \n'; expected += 'C | \n'; expected += '
|---|---|---|
| 1 | \n'; expected += '11 | \n'; expected += '111 | \n'; expected += '
| 2 | \n'; expected += '22 | \n'; expected += '|
| 3 | \n'; expected += '33 | \n'; expected += '
| A | \n'; expected += 'B | \n'; expected += 'C | \n'; expected += 'D | \n'; expected += '|
|---|---|---|---|---|
| 1 | \n'; expected += '11 | \n'; expected += '|||
| 2 | \n'; expected += '22 | \n'; expected += '222 | \n'; expected += '||
| 3 | \n'; expected += '33 | \n'; expected += '|||


paragraph code{.red}
code = {.red}bla click() blah release()
text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it(replaceDelimiters('should do nothing with empty classname {.}', options), () => { src = 'text {.}'; expected = 'text {.}
\n'; assert.equal(md.render(replaceDelimiters(src, options)), replaceDelimiters(expected, options)); }); it(replaceDelimiters('should do nothing with empty id {#}', options), () => { src = 'text {#}'; expected = 'text {#}
\n'; assert.equal(md.render(replaceDelimiters(src, options)), replaceDelimiters(expected, options)); }); it(replaceDelimiters('should support horizontal rules ---{#id}', options), () => { src = '---{#id}'; expected = 'text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it('should restrict attributes by allowedAttributes (regex)', () => { md = Md().use(attrs, Object.assign({ allowedAttributes: [/^(class|attr)$/] }, options)); src = 'text {.someclass #someid attr=allowed}'; expected = 'text
\n'; assert.equal(md.render(replaceDelimiters(src, options)), expected); }); it('should support multiple classes for