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 MarkupIt, { Syntax, JSONUtils } from 'markup-it';
|
||||
import MarkupIt, { Syntax, JSONUtils, BLOCKS, STYLES, ENTITIES } from 'markup-it';
|
||||
|
||||
const defaultRenderers = {
|
||||
'doc': 'article',
|
||||
'header_one': 'h1',
|
||||
'header_two': 'h2',
|
||||
'header_three': 'h3',
|
||||
'header_four': 'h4',
|
||||
'header_five': 'h5',
|
||||
'header_six': 'h6',
|
||||
'paragraph': 'p',
|
||||
'ordered_list': 'ol',
|
||||
'unordered_list': 'ul',
|
||||
'list_item': 'li',
|
||||
'link': 'a',
|
||||
'image': 'img',
|
||||
'BOLD': 'strong',
|
||||
'ITALIC': 'em',
|
||||
'text': null,
|
||||
'unstyled': null,
|
||||
[BLOCKS.DOCUMENT]: 'article',
|
||||
[BLOCKS.TEXT]: null,
|
||||
[BLOCKS.CODE]: 'code',
|
||||
[BLOCKS.BLOCKQUOTE]: 'blockquote',
|
||||
[BLOCKS.PARAGRAPH]: 'p',
|
||||
[BLOCKS.FOOTNOTE]: 'footnote',
|
||||
[BLOCKS.HTML]: (props) => null,
|
||||
[BLOCKS.HR]: 'hr',
|
||||
[BLOCKS.HEADING_1]: 'h1',
|
||||
[BLOCKS.HEADING_2]: 'h2',
|
||||
[BLOCKS.HEADING_3]: 'h3',
|
||||
[BLOCKS.HEADING_4]: 'h4',
|
||||
[BLOCKS.HEADING_5]: 'h5',
|
||||
[BLOCKS.HEADING_6]: 'h6',
|
||||
[BLOCKS.TABLE]: 'table',
|
||||
[BLOCKS.TABLE_ROW]: 'tr',
|
||||
[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') {
|
||||
const { type, data, text, tokens } = token;
|
||||
const element = defaultRenderers[type];
|
||||
const nodeType = defaultRenderers[type];
|
||||
key = `${key}.${index}`;
|
||||
|
||||
// Only render if type is registered as renderer
|
||||
if (typeof element !== 'undefined') {
|
||||
if (typeof nodeType !== 'undefined') {
|
||||
let children = null;
|
||||
if (Array.isArray(tokens) && tokens.length) {
|
||||
children = tokens.map((token, idx) => renderToken(token, idx, key));
|
||||
} else if (type === 'text') {
|
||||
children = text;
|
||||
}
|
||||
if (element !== null) {
|
||||
if (nodeType !== null) {
|
||||
// If this is a react element
|
||||
return React.createElement(
|
||||
element,
|
||||
nodeType,
|
||||
{ key, ...data }, // Add key as a prop
|
||||
Array.isArray(children) && children.length === 1
|
||||
? children[0] : children); // Pass single child if possible
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint max-len:0 */
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import markdownSyntax from 'markup-it/syntaxes/markdown';
|
||||
@ -5,39 +7,44 @@ import htmlSyntax from 'markup-it/syntaxes/html';
|
||||
import MarkitupReactRenderer from '../MarkitupReactRenderer';
|
||||
|
||||
describe('MarkitupReactRenderer', () => {
|
||||
it('should re-render properly after a value and syntax update', () => {
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value="# Title"
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree1 = component.html();
|
||||
component.setProps({
|
||||
value: '<h1>Title</h1>',
|
||||
syntax: htmlSyntax
|
||||
|
||||
describe('basics', () => {
|
||||
it('should re-render properly after a value and syntax update', () => {
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value="# Title"
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree1 = component.html();
|
||||
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', () => {
|
||||
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);
|
||||
});
|
||||
|
||||
it('should render markdown', () => {
|
||||
const value = `
|
||||
describe('Markdown rendering', () => {
|
||||
describe('General', () => {
|
||||
it('should render markdown', () => {
|
||||
const value = `
|
||||
# H1
|
||||
|
||||
Text with **bold** & _em_ elements
|
||||
@ -63,18 +70,69 @@ Text with **bold** & _em_ elements
|
||||
|
||||
###### H6
|
||||
`;
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render HTML as is using Markdown', () => {
|
||||
const value = `
|
||||
describe('Links', () => {
|
||||
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
|
||||
|
||||
<dl>
|
||||
@ -82,37 +140,43 @@ Text with **bold** & _em_ elements
|
||||
<dd>Testing HTML in Markdown</dd>
|
||||
</dl>
|
||||
`;
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should support custom syntax', () => {
|
||||
const value = '';
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
describe('custom elements', () => {
|
||||
it('should support custom syntax', () => {
|
||||
const value = '';
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={markdownSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render HTML', () => {
|
||||
const value = '<p class="test class">Paragraph with <em>inline</em> element</p>';
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={htmlSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
describe('HTML rendering', () => {
|
||||
it('should render HTML', () => {
|
||||
const value = '<p class="test class">Paragraph with <em>inline</em> element</p>';
|
||||
const component = shallow(
|
||||
<MarkitupReactRenderer
|
||||
value={value}
|
||||
syntax={htmlSyntax}
|
||||
/>
|
||||
);
|
||||
const tree = component.html();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user