Support more elements. Import dicitonaries from markup-it. Added more tests.
This commit is contained in:
parent
9392fdbe30
commit
57688af42e
@ -1,43 +1,57 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import MarkupIt, { Syntax, JSONUtils } from 'markup-it';
|
import MarkupIt, { Syntax, JSONUtils, BLOCKS, STYLES, ENTITIES } from 'markup-it';
|
||||||
|
|
||||||
const defaultRenderers = {
|
const defaultRenderers = {
|
||||||
'doc': 'article',
|
[BLOCKS.DOCUMENT]: 'article',
|
||||||
'header_one': 'h1',
|
[BLOCKS.TEXT]: null,
|
||||||
'header_two': 'h2',
|
[BLOCKS.CODE]: 'code',
|
||||||
'header_three': 'h3',
|
[BLOCKS.BLOCKQUOTE]: 'blockquote',
|
||||||
'header_four': 'h4',
|
[BLOCKS.PARAGRAPH]: 'p',
|
||||||
'header_five': 'h5',
|
[BLOCKS.FOOTNOTE]: 'footnote',
|
||||||
'header_six': 'h6',
|
[BLOCKS.HTML]: (props) => null,
|
||||||
'paragraph': 'p',
|
[BLOCKS.HR]: 'hr',
|
||||||
'ordered_list': 'ol',
|
[BLOCKS.HEADING_1]: 'h1',
|
||||||
'unordered_list': 'ul',
|
[BLOCKS.HEADING_2]: 'h2',
|
||||||
'list_item': 'li',
|
[BLOCKS.HEADING_3]: 'h3',
|
||||||
'link': 'a',
|
[BLOCKS.HEADING_4]: 'h4',
|
||||||
'image': 'img',
|
[BLOCKS.HEADING_5]: 'h5',
|
||||||
'BOLD': 'strong',
|
[BLOCKS.HEADING_6]: 'h6',
|
||||||
'ITALIC': 'em',
|
[BLOCKS.TABLE]: 'table',
|
||||||
'text': null,
|
[BLOCKS.TABLE_ROW]: 'tr',
|
||||||
'unstyled': null,
|
[BLOCKS.TABLE_CELL]: 'td',
|
||||||
|
[BLOCKS.OL_LIST]: 'ol',
|
||||||
|
[BLOCKS.UL_LIST]: 'ul',
|
||||||
|
[BLOCKS.LIST_ITEM]: 'li',
|
||||||
|
|
||||||
|
[STYLES.TEXT]: null,
|
||||||
|
[STYLES.BOLD]: 'strong',
|
||||||
|
[STYLES.ITALIC]: 'em',
|
||||||
|
[STYLES.CODE]: 'code',
|
||||||
|
[STYLES.STRIKETHROUGH]: 'del',
|
||||||
|
|
||||||
|
[ENTITIES.LINK]: 'a',
|
||||||
|
[ENTITIES.IMAGE]: 'img',
|
||||||
|
[ENTITIES.FOOTNOTE_REF]: 'sup',
|
||||||
|
[ENTITIES.HARD_BREAK]: 'br'
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderToken(token, index = 0, key = '0') {
|
function renderToken(token, index = 0, key = '0') {
|
||||||
const { type, data, text, tokens } = token;
|
const { type, data, text, tokens } = token;
|
||||||
const element = defaultRenderers[type];
|
const nodeType = defaultRenderers[type];
|
||||||
key = `${key}.${index}`;
|
key = `${key}.${index}`;
|
||||||
|
|
||||||
// Only render if type is registered as renderer
|
// Only render if type is registered as renderer
|
||||||
if (typeof element !== 'undefined') {
|
if (typeof nodeType !== 'undefined') {
|
||||||
let children = null;
|
let children = null;
|
||||||
if (Array.isArray(tokens) && tokens.length) {
|
if (Array.isArray(tokens) && tokens.length) {
|
||||||
children = tokens.map((token, idx) => renderToken(token, idx, key));
|
children = tokens.map((token, idx) => renderToken(token, idx, key));
|
||||||
} else if (type === 'text') {
|
} else if (type === 'text') {
|
||||||
children = text;
|
children = text;
|
||||||
}
|
}
|
||||||
if (element !== null) {
|
if (nodeType !== null) {
|
||||||
// If this is a react element
|
// If this is a react element
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
element,
|
nodeType,
|
||||||
{ key, ...data }, // Add key as a prop
|
{ key, ...data }, // Add key as a prop
|
||||||
Array.isArray(children) && children.length === 1
|
Array.isArray(children) && children.length === 1
|
||||||
? children[0] : children); // Pass single child if possible
|
? children[0] : children); // Pass single child if possible
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
/* eslint max-len:0 */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import markdownSyntax from 'markup-it/syntaxes/markdown';
|
import markdownSyntax from 'markup-it/syntaxes/markdown';
|
||||||
@ -5,39 +7,44 @@ import htmlSyntax from 'markup-it/syntaxes/html';
|
|||||||
import MarkitupReactRenderer from '../MarkitupReactRenderer';
|
import MarkitupReactRenderer from '../MarkitupReactRenderer';
|
||||||
|
|
||||||
describe('MarkitupReactRenderer', () => {
|
describe('MarkitupReactRenderer', () => {
|
||||||
it('should re-render properly after a value and syntax update', () => {
|
|
||||||
const component = shallow(
|
describe('basics', () => {
|
||||||
<MarkitupReactRenderer
|
it('should re-render properly after a value and syntax update', () => {
|
||||||
value="# Title"
|
const component = shallow(
|
||||||
syntax={markdownSyntax}
|
<MarkitupReactRenderer
|
||||||
/>
|
value="# Title"
|
||||||
);
|
syntax={markdownSyntax}
|
||||||
const tree1 = component.html();
|
/>
|
||||||
component.setProps({
|
);
|
||||||
value: '<h1>Title</h1>',
|
const tree1 = component.html();
|
||||||
syntax: htmlSyntax
|
component.setProps({
|
||||||
|
value: '<h1>Title</h1>',
|
||||||
|
syntax: htmlSyntax
|
||||||
|
});
|
||||||
|
const tree2 = component.html();
|
||||||
|
expect(tree1).toEqual(tree2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not update the parser if syntax didn\'t change', () => {
|
||||||
|
const component = shallow(
|
||||||
|
<MarkitupReactRenderer
|
||||||
|
value="# Title"
|
||||||
|
syntax={markdownSyntax}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const syntax1 = component.instance().props.syntax;
|
||||||
|
component.setProps({
|
||||||
|
value: '## Title',
|
||||||
|
});
|
||||||
|
const syntax2 = component.instance().props.syntax;
|
||||||
|
expect(syntax1).toEqual(syntax2);
|
||||||
});
|
});
|
||||||
const tree2 = component.html();
|
|
||||||
expect(tree1).toEqual(tree2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not update the parser if syntax didn\'t change', () => {
|
describe('Markdown rendering', () => {
|
||||||
const component = shallow(
|
describe('General', () => {
|
||||||
<MarkitupReactRenderer
|
it('should render markdown', () => {
|
||||||
value="# Title"
|
const value = `
|
||||||
syntax={markdownSyntax}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
const syntax1 = component.instance().props.syntax;
|
|
||||||
component.setProps({
|
|
||||||
value: '## Title',
|
|
||||||
});
|
|
||||||
const syntax2 = component.instance().props.syntax;
|
|
||||||
expect(syntax1).toEqual(syntax2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render markdown', () => {
|
|
||||||
const value = `
|
|
||||||
# H1
|
# H1
|
||||||
|
|
||||||
Text with **bold** & _em_ elements
|
Text with **bold** & _em_ elements
|
||||||
@ -63,18 +70,69 @@ Text with **bold** & _em_ elements
|
|||||||
|
|
||||||
###### H6
|
###### H6
|
||||||
`;
|
`;
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<MarkitupReactRenderer
|
<MarkitupReactRenderer
|
||||||
value={value}
|
value={value}
|
||||||
syntax={markdownSyntax}
|
syntax={markdownSyntax}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
const tree = component.html();
|
const tree = component.html();
|
||||||
expect(tree).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should render HTML as is using Markdown', () => {
|
describe('Links', () => {
|
||||||
const value = `
|
it('should render links', () => {
|
||||||
|
const value = `
|
||||||
|
I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3].
|
||||||
|
|
||||||
|
[1]: http://google.com/ "Google"
|
||||||
|
[2]: http://search.yahoo.com/ "Yahoo Search"
|
||||||
|
[3]: http://search.msn.com/ "MSN Search"
|
||||||
|
`;
|
||||||
|
const component = shallow(
|
||||||
|
<MarkitupReactRenderer
|
||||||
|
value={value}
|
||||||
|
syntax={markdownSyntax}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const tree = component.html();
|
||||||
|
const expected = '<article><p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p></article>';
|
||||||
|
expect(tree).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Code', () => {
|
||||||
|
it('should render code', () => {
|
||||||
|
const value = 'Use the `printf()` function.';
|
||||||
|
const component = shallow(
|
||||||
|
<MarkitupReactRenderer
|
||||||
|
value={value}
|
||||||
|
syntax={markdownSyntax}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const tree = component.html();
|
||||||
|
const expected = '<article><p>Use the <code>printf()</code> function.</p></article>';
|
||||||
|
expect(tree).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render code 2', () => {
|
||||||
|
const value = '``There is a literal backtick (`) here.``';
|
||||||
|
const component = shallow(
|
||||||
|
<MarkitupReactRenderer
|
||||||
|
value={value}
|
||||||
|
syntax={markdownSyntax}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const tree = component.html();
|
||||||
|
const expected = '<article><p><code>There is a literal backtick (`) here.</code></p></article>';
|
||||||
|
expect(tree).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('HTML', () => {
|
||||||
|
it('should render HTML as is using Markdown', () => {
|
||||||
|
const value = `
|
||||||
# Title
|
# Title
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
@ -82,37 +140,43 @@ Text with **bold** & _em_ elements
|
|||||||
<dd>Testing HTML in Markdown</dd>
|
<dd>Testing HTML in Markdown</dd>
|
||||||
</dl>
|
</dl>
|
||||||
`;
|
`;
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<MarkitupReactRenderer
|
<MarkitupReactRenderer
|
||||||
value={value}
|
value={value}
|
||||||
syntax={markdownSyntax}
|
syntax={markdownSyntax}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
const tree = component.html();
|
const tree = component.html();
|
||||||
expect(tree).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support custom syntax', () => {
|
describe('custom elements', () => {
|
||||||
const value = '';
|
it('should support custom syntax', () => {
|
||||||
const component = shallow(
|
const value = '';
|
||||||
<MarkitupReactRenderer
|
const component = shallow(
|
||||||
value={value}
|
<MarkitupReactRenderer
|
||||||
syntax={markdownSyntax}
|
value={value}
|
||||||
/>
|
syntax={markdownSyntax}
|
||||||
);
|
/>
|
||||||
const tree = component.html();
|
);
|
||||||
expect(tree).toMatchSnapshot();
|
const tree = component.html();
|
||||||
|
expect(tree).toMatchSnapshot();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render HTML', () => {
|
describe('HTML rendering', () => {
|
||||||
const value = '<p class="test class">Paragraph with <em>inline</em> element</p>';
|
it('should render HTML', () => {
|
||||||
const component = shallow(
|
const value = '<p class="test class">Paragraph with <em>inline</em> element</p>';
|
||||||
<MarkitupReactRenderer
|
const component = shallow(
|
||||||
value={value}
|
<MarkitupReactRenderer
|
||||||
syntax={htmlSyntax}
|
value={value}
|
||||||
/>
|
syntax={htmlSyntax}
|
||||||
);
|
/>
|
||||||
const tree = component.html();
|
);
|
||||||
expect(tree).toMatchSnapshot();
|
const tree = component.html();
|
||||||
|
expect(tree).toMatchSnapshot();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user