diff --git a/README.md b/README.md
index c87e1c7..830e75e 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
react-remarkable
-=================
+================
A React component for rendering Markdown with [remarkable](https://github.com/jonschlinkert/remarkable).
@@ -10,36 +10,29 @@ npm install --save react-remarkable
## Usage
```jsx
+import React from 'react';
+import Markdown from 'react-remarkable';
+import Emoji from 'remarkable-emoji';
-var React = require('react');
-var Markdown = require('react-remarkable');
+const MyComponent = () => (
+
+ {/* Pass Markdown source to the `source` prop */}
+
-var MyComponent = React.createClass({
+ {/* Or pass it as children */}
+ {/* You can nest React components, too */}
+
{`
+ ## Reasons React is great
- render() {
- return (
-
- {/* Pass Markdown source to the `source` prop */}
-
+ 1. Server-side rendering
+ 2. This totally works:
- {/* Or pass it as children */}
- {/* You can nest React components, too */}
- {`
- ## Reasons React is great
-
- 1. Server-side rendering
- 2. This totally works:
-
-
-
- Pretty neat!
- `}
-
- );
- }
-
-});
+
+ Pretty neat!
+ `}
+
+);
```
Available props:
@@ -47,6 +40,7 @@ Available props:
- `options` - Hash of Remarkable options
- `source` - Markdown source. You can also pass the source as children, which allows you to mix React components and Markdown.
- `container` - Element to use as container. Defaults to `div`.
+- `plugins` - Array of remarkable plugins
## Syntax Highlighting
diff --git a/dist/index.js b/dist/index.js
new file mode 100644
index 0000000..2001c61
--- /dev/null
+++ b/dist/index.js
@@ -0,0 +1,138 @@
+'use strict';
+
+Object.defineProperty(exports, '__esModule', {
+ value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var _react = require('react');
+
+var _react2 = _interopRequireDefault(_react);
+
+var _propTypes = require('prop-types');
+
+var _propTypes2 = _interopRequireDefault(_propTypes);
+
+var _remarkable = require('remarkable');
+
+var _remarkable2 = _interopRequireDefault(_remarkable);
+
+var Remarkable = (function (_React$Component) {
+ _inherits(Remarkable, _React$Component);
+
+ function Remarkable() {
+ _classCallCheck(this, Remarkable);
+
+ _get(Object.getPrototypeOf(Remarkable.prototype), 'constructor', this).apply(this, arguments);
+ }
+
+ _createClass(Remarkable, [{
+ key: 'componentWillUpdate',
+ value: function componentWillUpdate(nextProps, nextState) {
+ if (nextProps.options !== this.props.options) {
+ this.md = this.createMarkdown(nextProps.options, nextProps.plugins);
+ }
+ }
+ }, {
+ key: 'shouldComponentUpdate',
+ value: function shouldComponentUpdate(nextProps, nextState) {
+ if (nextProps.options !== this.props.options) {
+ return true;
+ } else if (this.props.source) {
+ return this.props.source !== nextProps.source;
+ } else if (_react2['default'].Children.count(this.props.children) === 1 && _react2['default'].Children.count(nextProps.children) === 1) {
+ return typeof this.props.children === 'string' && this.props.children !== nextProps.children;
+ } else {
+ return true;
+ }
+ }
+ }, {
+ key: 'renderMarkdown',
+ value: function renderMarkdown(source) {
+ if (!this.md) {
+ this.md = this.createMarkdown(this.props.options, this.props.plugins);
+ }
+
+ return this.md.render(source);
+ }
+ }, {
+ key: 'createMarkdown',
+ value: function createMarkdown(options, plugins) {
+ return plugins.reduce(function (md, plugin) {
+ return md.use(plugin);
+ }, new _remarkable2['default'](options));
+ }
+ }, {
+ key: 'render',
+ value: function render() {
+ var _this = this;
+
+ var _props =
+ // ⬆ remove Remarkable props
+ // ⬅ only pass non-Remarkable props
+ this.props;
+ var Container = _props.container;
+ var children = _props.children;
+ var options = _props.options;
+ var plugins = _props.plugins;
+ var source = _props.source;
+
+ var props = _objectWithoutProperties(_props, ['container', 'children', 'options', 'plugins', 'source']);
+
+ if (!children && !source) {
+ return null;
+ }
+
+ if (children) {
+ return _react2['default'].Children.map(children, function (child) {
+ if (typeof child === 'string') {
+ return _react2['default'].createElement(Container, _extends({}, props, {
+ dangerouslySetInnerHTML: {
+ __html: _this.renderMarkdown(child)
+ }
+ }));
+ }
+ return child;
+ });
+ }
+
+ return _react2['default'].createElement(Container, _extends({}, props, {
+ dangerouslySetInnerHTML: {
+ __html: this.renderMarkdown(source)
+ }
+ }));
+ }
+ }]);
+
+ return Remarkable;
+})(_react2['default'].Component);
+
+Remarkable.propTypes = {
+ children: _propTypes2['default'].oneOfType([_propTypes2['default'].arrayOf(_propTypes2['default'].node), _propTypes2['default'].node]),
+ container: _propTypes2['default'].string,
+ options: _propTypes2['default'].object,
+ plugins: _propTypes2['default'].arrayOf(_propTypes2['default'].string),
+ source: _propTypes2['default'].string
+};
+
+Remarkable.defaultProps = {
+ container: 'div',
+ options: {},
+ plugins: []
+};
+
+exports['default'] = Remarkable;
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/package.json b/package.json
index 02c890a..ddc5d3c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-remarkable",
- "version": "1.1.2",
+ "version": "1.1.3-alpha.4",
"description": "A React component for rendering Markdown with remarkable",
"main": "dist/index.js",
"repository": {
diff --git a/src/index.js b/src/index.js
index 46c7336..941b7bc 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,54 +1,103 @@
'use strict';
import React from 'react';
+import PropTypes from 'prop-types';
import Markdown from 'remarkable';
class Remarkable extends React.Component {
- render() {
- var Container = this.props.container;
-
- return (
-
- {this.content()}
-
- );
- }
-
componentWillUpdate(nextProps, nextState) {
if (nextProps.options !== this.props.options) {
- this.md = new Markdown(nextProps.options);
+ this.md = this.createMarkdown(nextProps.options, nextProps.plugins);
}
}
- content() {
- if (this.props.source) {
- return ;
+ shouldComponentUpdate(nextProps, nextState) {
+ if (nextProps.options !== this.props.options) {
+ return true;
+ }
+ else if (this.props.source) {
+ return this.props.source !== nextProps.source;
+ }
+ else if (React.Children.count(this.props.children) === 1 && React.Children.count(nextProps.children) === 1) {
+ return (typeof this.props.children === 'string') && this.props.children !== nextProps.children;
}
else {
- return React.Children.map(this.props.children, child => {
- if (typeof child === 'string') {
- return ;
- }
- else {
- return child;
- }
- });
+ return true;
}
}
renderMarkdown(source) {
if (!this.md) {
- this.md = new Markdown(this.props.options);
+ this.md = this.createMarkdown(this.props.options, this.props.plugins);
}
return this.md.render(source);
}
+
+ createMarkdown(options, plugins) {
+ return plugins.reduce((md, plugin) => {
+ return md.use(plugin);
+ }, new Markdown(options));
+ }
+
+ render() {
+ var {
+ container: Container,
+ children,
+ options,
+ plugins,
+ source,
+ // ⬆ remove Remarkable props
+ ...props // ⬅ only pass non-Remarkable props
+ } = this.props;
+
+ if (!children && !source) {
+ return null;
+ }
+
+ if (children) {
+ return React.Children.map(children, child => {
+ if (typeof child === 'string') {
+ return (
+
+ );
+ }
+ return child;
+ });
+ }
+
+ return (
+
+ );
+ }
}
+Remarkable.propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.node),
+ PropTypes.node,
+ ]),
+ container: PropTypes.string,
+ options: PropTypes.object,
+ plugins: PropTypes.arrayOf(PropTypes.string),
+ source: PropTypes.string,
+};
+
Remarkable.defaultProps = {
container: 'div',
options: {},
+ plugins: [],
};
export default Remarkable;