1020 lines
25 KiB
JavaScript
1020 lines
25 KiB
JavaScript
|
const Lexer = require('../../src/Lexer.js');
|
|||
|
|
|||
|
function expectTokens({ md, options, tokens = [], links = {} }) {
|
|||
|
const lexer = new Lexer(options);
|
|||
|
const actual = lexer.lex(md);
|
|||
|
const expected = tokens;
|
|||
|
expected.links = links;
|
|||
|
// console.log(JSON.stringify(actual, null, 2));
|
|||
|
expect(actual).toEqual(expected);
|
|||
|
}
|
|||
|
|
|||
|
function expectInlineOutput({ md, options, output = jasmine.any(String), tokens = jasmine.any(Array), links = {} }) {
|
|||
|
const lexer = new Lexer(options);
|
|||
|
lexer.tokens.links = links;
|
|||
|
const outTokens = [];
|
|||
|
const outOutput = lexer.inlineOutput(md, outTokens);
|
|||
|
expect({
|
|||
|
output: outOutput,
|
|||
|
tokens: outTokens
|
|||
|
}).toEqual({ output, tokens });
|
|||
|
}
|
|||
|
|
|||
|
function expectInlineTokens({ token, options, tokens }) {
|
|||
|
const lexer = new Lexer(options);
|
|||
|
lexer.inlineTokens([token]);
|
|||
|
expect(token.tokens).toEqual(tokens);
|
|||
|
}
|
|||
|
|
|||
|
describe('Lexer', () => {
|
|||
|
describe('paragraph', () => {
|
|||
|
it('space between paragraphs', () => {
|
|||
|
expectTokens({
|
|||
|
md: 'paragraph 1\n\nparagraph 2',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'paragraph',
|
|||
|
raw: 'paragraph 1',
|
|||
|
text: 'paragraph 1',
|
|||
|
tokens: [{ type: 'text', raw: 'paragraph 1', text: 'paragraph 1' }]
|
|||
|
},
|
|||
|
{ type: 'space', raw: '\n\n' },
|
|||
|
{
|
|||
|
type: 'paragraph',
|
|||
|
raw: 'paragraph 2',
|
|||
|
text: 'paragraph 2',
|
|||
|
tokens: [{ type: 'text', raw: 'paragraph 2', text: 'paragraph 2' }]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('code', () => {
|
|||
|
it('indented code', () => {
|
|||
|
expectTokens({
|
|||
|
md: ' code',
|
|||
|
tokens: [
|
|||
|
{ type: 'code', raw: ' code', text: 'code', codeBlockStyle: 'indented' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('fenced code', () => {
|
|||
|
expectTokens({
|
|||
|
md: '```\ncode\n```',
|
|||
|
tokens: [
|
|||
|
{ type: 'code', raw: '```\ncode\n```', text: 'code', lang: '' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('fenced code lang', () => {
|
|||
|
expectTokens({
|
|||
|
md: '```text\ncode\n```',
|
|||
|
tokens: [
|
|||
|
{ type: 'code', raw: '```text\ncode\n```', text: 'code', lang: 'text' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('headings', () => {
|
|||
|
it('depth', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
# heading 1
|
|||
|
|
|||
|
## heading 2
|
|||
|
|
|||
|
### heading 3
|
|||
|
|
|||
|
#### heading 4
|
|||
|
|
|||
|
##### heading 5
|
|||
|
|
|||
|
###### heading 6
|
|||
|
|
|||
|
lheading 1
|
|||
|
==========
|
|||
|
|
|||
|
lheading 2
|
|||
|
----------
|
|||
|
`,
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: '# heading 1\n\n',
|
|||
|
depth: 1,
|
|||
|
text: 'heading 1',
|
|||
|
tokens: [{ type: 'text', raw: 'heading 1', text: 'heading 1' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: '## heading 2\n\n',
|
|||
|
depth: 2,
|
|||
|
text: 'heading 2',
|
|||
|
tokens: [{ type: 'text', raw: 'heading 2', text: 'heading 2' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: '### heading 3\n\n',
|
|||
|
depth: 3,
|
|||
|
text: 'heading 3',
|
|||
|
tokens: [{ type: 'text', raw: 'heading 3', text: 'heading 3' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: '#### heading 4\n\n',
|
|||
|
depth: 4,
|
|||
|
text: 'heading 4',
|
|||
|
tokens: [{ type: 'text', raw: 'heading 4', text: 'heading 4' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: '##### heading 5\n\n',
|
|||
|
depth: 5,
|
|||
|
text: 'heading 5',
|
|||
|
tokens: [{ type: 'text', raw: 'heading 5', text: 'heading 5' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: '###### heading 6\n\n',
|
|||
|
depth: 6,
|
|||
|
text: 'heading 6',
|
|||
|
tokens: [{ type: 'text', raw: 'heading 6', text: 'heading 6' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: 'lheading 1\n==========\n\n',
|
|||
|
depth: 1,
|
|||
|
text: 'lheading 1',
|
|||
|
tokens: [{ type: 'text', raw: 'lheading 1', text: 'lheading 1' }]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'heading',
|
|||
|
raw: 'lheading 2\n----------\n',
|
|||
|
depth: 2,
|
|||
|
text: 'lheading 2',
|
|||
|
tokens: [{ type: 'text', raw: 'lheading 2', text: 'lheading 2' }]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('should not be heading if depth > 6', () => {
|
|||
|
expectTokens({
|
|||
|
md: '####### heading 7',
|
|||
|
tokens: [{
|
|||
|
type: 'paragraph',
|
|||
|
raw: '####### heading 7',
|
|||
|
text: '####### heading 7',
|
|||
|
tokens: [{ type: 'text', raw: '####### heading 7', text: '####### heading 7' }]
|
|||
|
}]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('table', () => {
|
|||
|
it('pipe table', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
| a | b |
|
|||
|
|---|---|
|
|||
|
| 1 | 2 |
|
|||
|
`,
|
|||
|
tokens: [{
|
|||
|
type: 'table',
|
|||
|
header: ['a', 'b'],
|
|||
|
align: [null, null],
|
|||
|
cells: [['1', '2']],
|
|||
|
raw: '| a | b |\n|---|---|\n| 1 | 2 |\n',
|
|||
|
tokens: {
|
|||
|
header: [
|
|||
|
[{ type: 'text', raw: 'a', text: 'a' }],
|
|||
|
[{ type: 'text', raw: 'b', text: 'b' }]
|
|||
|
],
|
|||
|
cells: [[
|
|||
|
[{ type: 'text', raw: '1', text: '1' }],
|
|||
|
[{ type: 'text', raw: '2', text: '2' }]
|
|||
|
]]
|
|||
|
}
|
|||
|
}]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('align table', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
| a | b | c |
|
|||
|
|:--|:-:|--:|
|
|||
|
| 1 | 2 | 3 |
|
|||
|
`,
|
|||
|
tokens: [{
|
|||
|
type: 'table',
|
|||
|
header: ['a', 'b', 'c'],
|
|||
|
align: ['left', 'center', 'right'],
|
|||
|
cells: [['1', '2', '3']],
|
|||
|
raw: '| a | b | c |\n|:--|:-:|--:|\n| 1 | 2 | 3 |\n',
|
|||
|
tokens: {
|
|||
|
header: [
|
|||
|
[{ type: 'text', raw: 'a', text: 'a' }],
|
|||
|
[{ type: 'text', raw: 'b', text: 'b' }],
|
|||
|
[{ type: 'text', raw: 'c', text: 'c' }]
|
|||
|
],
|
|||
|
cells: [[
|
|||
|
[{ type: 'text', raw: '1', text: '1' }],
|
|||
|
[{ type: 'text', raw: '2', text: '2' }],
|
|||
|
[{ type: 'text', raw: '3', text: '3' }]
|
|||
|
]]
|
|||
|
}
|
|||
|
}]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('no pipe table', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
a | b
|
|||
|
--|--
|
|||
|
1 | 2
|
|||
|
`,
|
|||
|
tokens: [{
|
|||
|
type: 'table',
|
|||
|
header: ['a', 'b'],
|
|||
|
align: [null, null],
|
|||
|
cells: [['1', '2']],
|
|||
|
raw: 'a | b\n--|--\n1 | 2\n',
|
|||
|
tokens: {
|
|||
|
header: [
|
|||
|
[{ type: 'text', raw: 'a', text: 'a' }],
|
|||
|
[{ type: 'text', raw: 'b', text: 'b' }]
|
|||
|
],
|
|||
|
cells: [[
|
|||
|
[{ type: 'text', raw: '1', text: '1' }],
|
|||
|
[{ type: 'text', raw: '2', text: '2' }]
|
|||
|
]]
|
|||
|
}
|
|||
|
}]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('hr', () => {
|
|||
|
it('hr', () => {
|
|||
|
expectTokens({
|
|||
|
md: '---',
|
|||
|
tokens: [
|
|||
|
{ type: 'hr', raw: '---' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('blockquote', () => {
|
|||
|
it('start, inner-tokens, end', () => {
|
|||
|
expectTokens({
|
|||
|
md: '> blockquote',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'blockquote',
|
|||
|
raw: '> blockquote',
|
|||
|
tokens: [{
|
|||
|
type: 'paragraph',
|
|||
|
raw: 'blockquote',
|
|||
|
text: 'blockquote',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'blockquote', text: 'blockquote' }
|
|||
|
]
|
|||
|
}]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('list', () => {
|
|||
|
it('unordered', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
- item 1
|
|||
|
- item 2
|
|||
|
`,
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'list',
|
|||
|
raw: '- item 1\n- item 2\n',
|
|||
|
ordered: false,
|
|||
|
start: '',
|
|||
|
loose: false,
|
|||
|
items: [
|
|||
|
{
|
|||
|
raw: '- item 1',
|
|||
|
task: false,
|
|||
|
checked: undefined,
|
|||
|
loose: false,
|
|||
|
tokens: [{
|
|||
|
type: 'text',
|
|||
|
raw: 'item 1',
|
|||
|
text: 'item 1',
|
|||
|
tokens: [{ type: 'text', raw: 'item 1', text: 'item 1' }]
|
|||
|
}]
|
|||
|
},
|
|||
|
{
|
|||
|
raw: '- item 2',
|
|||
|
task: false,
|
|||
|
checked: undefined,
|
|||
|
loose: false,
|
|||
|
tokens: [{
|
|||
|
type: 'text',
|
|||
|
raw: 'item 2',
|
|||
|
text: 'item 2',
|
|||
|
tokens: [{ type: 'text', raw: 'item 2', text: 'item 2' }]
|
|||
|
}]
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('ordered', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
1. item 1
|
|||
|
2. item 2
|
|||
|
`,
|
|||
|
tokens: jasmine.arrayContaining([
|
|||
|
jasmine.objectContaining({
|
|||
|
type: 'list',
|
|||
|
raw: '1. item 1\n2. item 2\n',
|
|||
|
ordered: true,
|
|||
|
start: 1,
|
|||
|
items: [
|
|||
|
jasmine.objectContaining({
|
|||
|
raw: '1. item 1'
|
|||
|
}),
|
|||
|
jasmine.objectContaining({
|
|||
|
raw: '2. item 2'
|
|||
|
})
|
|||
|
]
|
|||
|
})
|
|||
|
])
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('start', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
2. item 1
|
|||
|
3. item 2
|
|||
|
`,
|
|||
|
tokens: jasmine.arrayContaining([
|
|||
|
jasmine.objectContaining({
|
|||
|
type: 'list',
|
|||
|
raw: '2. item 1\n3. item 2\n',
|
|||
|
ordered: true,
|
|||
|
start: 2,
|
|||
|
items: [
|
|||
|
jasmine.objectContaining({
|
|||
|
raw: '2. item 1'
|
|||
|
}),
|
|||
|
jasmine.objectContaining({
|
|||
|
raw: '3. item 2'
|
|||
|
})
|
|||
|
]
|
|||
|
})
|
|||
|
])
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('loose', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
- item 1
|
|||
|
|
|||
|
- item 2
|
|||
|
`,
|
|||
|
tokens: jasmine.arrayContaining([
|
|||
|
jasmine.objectContaining({
|
|||
|
type: 'list',
|
|||
|
raw: '- item 1\n\n- item 2\n',
|
|||
|
loose: true
|
|||
|
})
|
|||
|
])
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('task', () => {
|
|||
|
expectTokens({
|
|||
|
md: `
|
|||
|
- [ ] item 1
|
|||
|
- [x] item 2
|
|||
|
`,
|
|||
|
tokens: jasmine.arrayContaining([
|
|||
|
jasmine.objectContaining({
|
|||
|
type: 'list',
|
|||
|
raw: '- [ ] item 1\n- [x] item 2\n',
|
|||
|
items: [
|
|||
|
jasmine.objectContaining({
|
|||
|
raw: '- [ ] item 1',
|
|||
|
task: true,
|
|||
|
checked: false
|
|||
|
}),
|
|||
|
jasmine.objectContaining({
|
|||
|
raw: '- [x] item 2',
|
|||
|
task: true,
|
|||
|
checked: true
|
|||
|
})
|
|||
|
]
|
|||
|
})
|
|||
|
])
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('html', () => {
|
|||
|
it('div', () => {
|
|||
|
expectTokens({
|
|||
|
md: '<div>html</div>',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'html',
|
|||
|
raw: '<div>html</div>',
|
|||
|
pre: false,
|
|||
|
text: '<div>html</div>'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('pre', () => {
|
|||
|
expectTokens({
|
|||
|
md: '<pre>html</pre>',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'html',
|
|||
|
raw: '<pre>html</pre>',
|
|||
|
pre: true,
|
|||
|
text: '<pre>html</pre>'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('sanitize', () => {
|
|||
|
expectTokens({
|
|||
|
md: '<div>html</div>',
|
|||
|
options: { sanitize: true },
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'paragraph',
|
|||
|
raw: '<div>html</div>',
|
|||
|
pre: false,
|
|||
|
text: '<div>html</div>',
|
|||
|
tokens: [{
|
|||
|
type: 'text',
|
|||
|
raw: '<div>html</div>',
|
|||
|
text: '<div>html</div>'
|
|||
|
}]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('def', () => {
|
|||
|
it('link', () => {
|
|||
|
expectTokens({
|
|||
|
md: '[link]: https://example.com',
|
|||
|
links: {
|
|||
|
link: { href: 'https://example.com', title: undefined }
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('title', () => {
|
|||
|
expectTokens({
|
|||
|
md: '[link]: https://example.com "title"',
|
|||
|
links: {
|
|||
|
link: { href: 'https://example.com', title: 'title' }
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('inline', () => {
|
|||
|
describe('tokens', () => {
|
|||
|
it('paragraph', () => {
|
|||
|
expectInlineTokens({
|
|||
|
token: { type: 'paragraph', text: 'text' },
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'text', text: 'text' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('text', () => {
|
|||
|
expectInlineTokens({
|
|||
|
token: { type: 'text', text: 'text' },
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'text', text: 'text' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('heading', () => {
|
|||
|
expectInlineTokens({
|
|||
|
token: { type: 'heading', text: 'text' },
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'text', text: 'text' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('table', () => {
|
|||
|
expectInlineTokens({
|
|||
|
token: {
|
|||
|
type: 'table',
|
|||
|
header: ['a', 'b'],
|
|||
|
align: [null, null],
|
|||
|
cells: [['1', '2']]
|
|||
|
},
|
|||
|
tokens: {
|
|||
|
header: [
|
|||
|
[{ type: 'text', raw: 'a', text: 'a' }],
|
|||
|
[{ type: 'text', raw: 'b', text: 'b' }]
|
|||
|
],
|
|||
|
cells: [
|
|||
|
[
|
|||
|
[{ type: 'text', raw: '1', text: '1' }],
|
|||
|
[{ type: 'text', raw: '2', text: '2' }]
|
|||
|
]
|
|||
|
]
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('code no inline tokens', () => {
|
|||
|
expectInlineTokens({
|
|||
|
token: { type: 'code', text: 'code' },
|
|||
|
tokens: undefined
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('output', () => {
|
|||
|
it('escape', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '\\>',
|
|||
|
output: '>',
|
|||
|
tokens: [
|
|||
|
{ type: 'escape', raw: '\\>', text: '>' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('html', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '<div>html</div>',
|
|||
|
output: '<div>html</div>',
|
|||
|
tokens: [
|
|||
|
{ type: 'html', raw: '<div>', text: '<div>' },
|
|||
|
{ type: 'text', raw: 'html', text: 'html' },
|
|||
|
{ type: 'html', raw: '</div>', text: '</div>' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('html sanitize', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '<div>html</div>',
|
|||
|
options: { sanitize: true },
|
|||
|
output: '<div>html</div>',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: '<div>', text: '<div>' },
|
|||
|
{ type: 'text', raw: 'html', text: 'html' },
|
|||
|
{ type: 'text', raw: '</div>', text: '</div>' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('link', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '[link](https://example.com)',
|
|||
|
output: 'link',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '[link](https://example.com)',
|
|||
|
text: 'link',
|
|||
|
href: 'https://example.com',
|
|||
|
title: null,
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'link', text: 'link' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('link title', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '[link](https://example.com "title")',
|
|||
|
output: 'link',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '[link](https://example.com "title")',
|
|||
|
text: 'link',
|
|||
|
href: 'https://example.com',
|
|||
|
title: 'title',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'link', text: 'link' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('image', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '',
|
|||
|
output: 'image',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'image',
|
|||
|
raw: '',
|
|||
|
text: 'image',
|
|||
|
href: 'https://example.com/image.png',
|
|||
|
title: null
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('image title', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '',
|
|||
|
output: 'image',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'image',
|
|||
|
raw: '',
|
|||
|
text: 'image',
|
|||
|
href: 'https://example.com/image.png',
|
|||
|
title: 'title'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('reflink', () => {
|
|||
|
it('reflink', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '[link][]',
|
|||
|
links: {
|
|||
|
link: { href: 'https://example.com', title: 'title' }
|
|||
|
},
|
|||
|
output: 'link',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '[link][]',
|
|||
|
text: 'link',
|
|||
|
href: 'https://example.com',
|
|||
|
title: 'title',
|
|||
|
tokens: [{
|
|||
|
type: 'text',
|
|||
|
raw: 'link',
|
|||
|
text: 'link'
|
|||
|
}]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('nolink', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '[link]',
|
|||
|
links: {
|
|||
|
link: { href: 'https://example.com', title: 'title' }
|
|||
|
},
|
|||
|
output: 'link',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '[link]',
|
|||
|
text: 'link',
|
|||
|
href: 'https://example.com',
|
|||
|
title: 'title',
|
|||
|
tokens: [{
|
|||
|
type: 'text',
|
|||
|
raw: 'link',
|
|||
|
text: 'link'
|
|||
|
}]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('no def', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '[link]',
|
|||
|
output: '[link]',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: '[', text: '[' },
|
|||
|
{ type: 'text', raw: 'link]', text: 'link]' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('strong', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '**strong**',
|
|||
|
output: 'strong',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'strong',
|
|||
|
raw: '**strong**',
|
|||
|
text: 'strong',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'strong', text: 'strong' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('em', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '*em*',
|
|||
|
output: 'em',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'em',
|
|||
|
raw: '*em*',
|
|||
|
text: 'em',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'em', text: 'em' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('code', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '`code`',
|
|||
|
output: 'code',
|
|||
|
tokens: [
|
|||
|
{ type: 'codespan', raw: '`code`', text: 'code' }
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('br', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'a\nb',
|
|||
|
options: { gfm: true, breaks: true },
|
|||
|
output: 'a\nb',
|
|||
|
tokens: jasmine.arrayContaining([
|
|||
|
{ type: 'br', raw: '\n' }
|
|||
|
])
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('del', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '~~del~~',
|
|||
|
output: 'del',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'del',
|
|||
|
raw: '~~del~~',
|
|||
|
text: 'del',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'del', text: 'del' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('url', () => {
|
|||
|
it('autolink', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '<https://example.com>',
|
|||
|
output: 'https://example.com',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '<https://example.com>',
|
|||
|
text: 'https://example.com',
|
|||
|
href: 'https://example.com',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'https://example.com', text: 'https://example.com' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('autolink email', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '<test@example.com>',
|
|||
|
options: { mangle: false },
|
|||
|
output: 'test@example.com',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '<test@example.com>',
|
|||
|
text: 'test@example.com',
|
|||
|
href: 'mailto:test@example.com',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'test@example.com', text: 'test@example.com' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('autolink mangle email', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '<test@example.com>',
|
|||
|
options: { mangle: true },
|
|||
|
output: jasmine.stringMatching('&#'),
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: '<test@example.com>',
|
|||
|
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|||
|
href: jasmine.stringMatching(/^mailto:(&#x?[0-9a-f]+;)+$/),
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|||
|
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/)
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('url', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'https://example.com',
|
|||
|
output: 'https://example.com',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: 'https://example.com',
|
|||
|
text: 'https://example.com',
|
|||
|
href: 'https://example.com',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'https://example.com', text: 'https://example.com' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('url email', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'test@example.com',
|
|||
|
options: { gfm: true, mangle: false },
|
|||
|
output: 'test@example.com',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: 'test@example.com',
|
|||
|
text: 'test@example.com',
|
|||
|
href: 'mailto:test@example.com',
|
|||
|
tokens: [
|
|||
|
{ type: 'text', raw: 'test@example.com', text: 'test@example.com' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('url mangle email', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'test@example.com',
|
|||
|
options: { gfm: true, mangle: true },
|
|||
|
output: jasmine.stringMatching('&#'),
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'link',
|
|||
|
raw: 'test@example.com',
|
|||
|
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|||
|
href: jasmine.stringMatching(/^mailto:(&#x?[0-9a-f]+;)+$/),
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/),
|
|||
|
text: jasmine.stringMatching(/^(&#x?[0-9a-f]+;)+$/)
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('text', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'text',
|
|||
|
output: 'text',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: 'text',
|
|||
|
text: 'text'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
describe('smartypants', () => {
|
|||
|
it('single quotes', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: "'single quotes'",
|
|||
|
options: { smartypants: true },
|
|||
|
output: '‘single quotes’',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: "'single quotes'",
|
|||
|
text: '‘single quotes’'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('double quotes', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: '"double quotes"',
|
|||
|
options: { smartypants: true },
|
|||
|
output: '“double quotes”',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: '"double quotes"',
|
|||
|
text: '“double quotes”'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('ellipses', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'ellipses...',
|
|||
|
options: { smartypants: true },
|
|||
|
output: 'ellipses…',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: 'ellipses...',
|
|||
|
text: 'ellipses…'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('en-dash', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'en--dash',
|
|||
|
options: { smartypants: true },
|
|||
|
output: 'en–dash',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: 'en--dash',
|
|||
|
text: 'en–dash'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
it('em-dash', () => {
|
|||
|
expectInlineOutput({
|
|||
|
md: 'em---dash',
|
|||
|
options: { smartypants: true },
|
|||
|
output: 'em—dash',
|
|||
|
tokens: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
raw: 'em---dash',
|
|||
|
text: 'em—dash'
|
|||
|
}
|
|||
|
]
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
});
|