WIP on React renderer for any Markit-up syntax

This commit is contained in:
Andrey Okonetchnikov 2016-09-22 17:36:02 +02:00
parent 862b85e4c3
commit 95008d8607
3 changed files with 229 additions and 0 deletions

View File

@ -0,0 +1,69 @@
import React, { PropTypes } from 'react';
import MarkupIt, { Syntax, JSONUtils } 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,
};
export default class MarkitupReactRenderer extends React.Component {
renderToken = (token) => {
const { type, data, text, tokens } = token;
const element = defaultRenderers[type];
// Only render if type is registered as renderer
if (typeof element !== 'undefined') {
let children = null;
if (Array.isArray(tokens) && tokens.length) {
children = tokens.map(this.renderToken);
} else if (type === 'text') {
children = text;
}
if (element !== null) {
// If this is a react element
return React.createElement(element, data, children);
} else {
// If this is a text node
return children;
}
}
return null;
}
render() {
const { value, syntax } = this.props;
if (typeof this.parser === 'undefined') {
this.parser = new MarkupIt(syntax);
}
const content = this.parser.toContent(value);
const json = JSONUtils.encode(content);
// console.log(JSON.stringify(json, null, 2));
return (
<div>{this.renderToken(json.token)}</div>
);
}
}
MarkitupReactRenderer.propTypes = {
value: PropTypes.string,
syntax: PropTypes.instanceOf(Syntax).isRequired
};

View File

@ -0,0 +1,70 @@
import React from 'react';
import renderer from 'react-test-renderer';
import markdownSyntax from 'markup-it/syntaxes/markdown';
import htmlSyntax from 'markup-it/syntaxes/html';
import MarkitupReactRenderer from '../MarkitupReactRenderer';
describe('MarkitupReactRenderer', () => {
it('should render markdown', () => {
const value = `
# H1
Text with **bold** & _em_ elements
## H2
* ul item 1
* ul item 2
### H3
1. ol item 1
1. ol item 2
1. ol item 3
#### H4
[link title](http://google.com)
##### H5
![alt text](https://pbs.twimg.com/profile_images/678903331176214528/TQTdqGwD.jpg)
###### H6
`;
const component = renderer.create(
<MarkitupReactRenderer
value={value}
syntax={markdownSyntax}
/>
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('should support custom syntax', () => {
const value = `
`;
const component = renderer.create(
<MarkitupReactRenderer
value={value}
syntax={markdownSyntax}
/>
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('should render HTML', () => {
const value = '<p class="test class">Paragraph with <em>inline</em> element</p>';
const component = renderer.create(
<MarkitupReactRenderer
value={value}
syntax={htmlSyntax}
/>
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View File

@ -0,0 +1,90 @@
exports[`MarkitupReactRenderer should render HTML 1`] = `
<div>
<article>
<p>
Paragraph with
<em>
inline
</em>
element
</p>
</article>
</div>
`;
exports[`MarkitupReactRenderer should render markdown 1`] = `
<div>
<article>
<h1
id={null}>
H1
</h1>
<p>
Text with
<strong>
bold
</strong>
&
<em>
em
</em>
elements
</p>
<h2
id={null}>
H2
</h2>
<ul>
<li
loose={false}>
ul item 1
</li>
<li
loose={false}>
ul item 2
</li>
</ul>
<h3
id={null}>
H3
</h3>
<ol>
<li
loose={false}>
ol item 1
</li>
<li
loose={false}>
ol item 2
</li>
<li
loose={false}>
ol item 3
</li>
</ol>
<h4
id={null}>
H4
</h4>
<p>
<a
href="http://google.com">
link title
</a>
</p>
<h5
id={null}>
H5
</h5>
<p>
<img
alt="alt text"
src="https://pbs.twimg.com/profile_images/678903331176214528/TQTdqGwD.jpg" />
</p>
<h6
id={null}>
H6
</h6>
</article>
</div>
`;