Skip to content

Commit

Permalink
Merge pull request mientjan#125 from okwast/chore/rework-index-file-r…
Browse files Browse the repository at this point in the history
…emove-depricated-functions

Reworks the Markdown component to a functional component while also ...
  • Loading branch information
ardeaf committed Nov 4, 2019
2 parents 81bfc3c + e1511e0 commit 0f386b3
Showing 1 changed file with 92 additions and 160 deletions.
252 changes: 92 additions & 160 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
* Base Markdown component
* @author Mient-jan Stelling
*/
import React, { Component } from 'react';
import { useMemo } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import parser from './lib/parser';
import applyStyle from './lib/util/applyStyle';
import getUniqueID from './lib/util/getUniqueID';
Expand Down Expand Up @@ -38,178 +37,111 @@ export {
};

/**
* react-native-markdown-renderer
*
* @param children
* @return {string}
*/
export default class Markdown extends Component {
/**
* Definition of the prop types
*/
static propTypes = {
children: PropTypes.node.isRequired,
renderer: PropTypes.oneOfType([PropTypes.func, PropTypes.instanceOf(AstRenderer)]),
rules: (props, propName, componentName) => {
let invalidProps = [];
const prop = props[propName];
const getCopyFromChildren = children => {
return children instanceof Array ? children.join('') : children;
};

if (!prop) {
return;
}
const getRenderer = (renderer, rules, style) => {
if (renderer && rules) {
console.warn(
'react-native-markdown-renderer you are using renderer and rules at the same time. This is not possible, props.rules is ignored'
);
}

if (typeof prop === 'object') {
invalidProps = Object.keys(prop).filter(key => typeof prop[key] !== 'function');
}
if (renderer && style) {
console.warn(
'react-native-markdown-renderer you are using renderer and style at the same time. This is not possible, props.style is ignored'
);
}

if (typeof prop !== 'object') {
return new Error(
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. Must be of shape {[index:string]:function} `
);
} else if (invalidProps.length > 0) {
return new Error(
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. These ` +
`props are not of type function \`${invalidProps.join(', ')}\` `
);
// these checks are here to prevent extra overhead.
if (renderer) {
if (!(typeof renderer === 'function') || renderer instanceof AstRenderer) {
return renderer;
} else {
throw new Error('Provided renderer is not compatible with function or AstRenderer. please change');
}
} else {
return new AstRenderer(
{
...renderRules,
...(rules || {}),
},
{
...styles,
...style,
}
},
markdownit: PropTypes.instanceOf(MarkdownIt),
plugins: PropTypes.arrayOf(PropTypes.instanceOf(PluginContainer)),
style: PropTypes.any,
};
);
}
};

/**
* Default Props
*/
static defaultProps = {
renderer: null,
rules: null,
plugins: [],
style: null,
markdownit: MarkdownIt({
typographer: true,
}),
};
const getMarkdownParser = (markdownit, plugins) => {
let md = markdownit;
if (plugins && plugins.length > 0) {
plugins.forEach(plugin => {
md = md.use.apply(md, plugin.toArray());
});
}

copy = '';
renderer = null;
markdownParser = null;
return md;
};

/**
* Only when the copy changes will the markdown render again.
* @param nextProps
* @param nextState
* @return {boolean}
*/
shouldComponentUpdate(nextProps, nextState) {
const copy = this.getCopyFromChildren(nextProps.children);
/**
* react-native-markdown-renderer
*/
const Markdown = ({
children,
renderer = null,
rules = null,
plugins = [],
style = null,
markdownit = MarkdownIt({
typographer: true,
}),
}) => {
const momoizedRenderer = useMemo(() => getRenderer(renderer, rules, style), [renderer, rules, style]);
const markdownParser = useMemo(() => getMarkdownParser(markdownit, plugins), [markdownit, plugins]);

const copy = (this.copy = getCopyFromChildren(children));
return parser(copy, momoizedRenderer.render, markdownParser);
};

if (copy !== this.copy) {
this.copy = copy;
return true;
/**
* Definition of the prop types
*/
Markdown.propTypes = {
children: PropTypes.node.isRequired,
renderer: PropTypes.oneOfType([PropTypes.func, PropTypes.instanceOf(AstRenderer)]),
rules: (props, propName, componentName) => {
let invalidProps = [];
const prop = props[propName];

if (!prop) {
return;
}

if (
nextProps.renderer !== this.props.renderer ||
nextProps.style !== this.props.style ||
nextProps.plugins !== this.props.plugins ||
nextProps.rules !== this.props.rules ||
nextProps.markdownit !== this.props.markdownit
) {
return true;
if (typeof prop === 'object') {
invalidProps = Object.keys(prop).filter(key => typeof prop[key] !== 'function');
}

return false;
}

/**
*
* @param props
*/
updateSettings(props = this.props) {
const { renderer, rules, style, plugins, markdownit } = props;

if (renderer && rules) {
console.warn(
'react-native-markdown-renderer you are using renderer and rules at the same time. This is not possible, props.rules is ignored'
if (typeof prop !== 'object') {
return new Error(
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. Must be of shape {[index:string]:function} `
);
}

if (renderer && style) {
console.warn(
'react-native-markdown-renderer you are using renderer and style at the same time. This is not possible, props.style is ignored'
} else if (invalidProps.length > 0) {
return new Error(
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. These ` +
`props are not of type function \`${invalidProps.join(', ')}\` `
);
}
},
markdownit: PropTypes.instanceOf(MarkdownIt),
plugins: PropTypes.arrayOf(PropTypes.instanceOf(PluginContainer)),
style: PropTypes.any,
};

// these checks are here to prevent extra overhead.
if (renderer) {
if (typeof renderer === 'function') {
if (!this.renderer || this.renderer.render !== renderer) {
this.renderer = {
render: renderer,
};
}
} else if (renderer instanceof AstRenderer) {
if (this.renderer !== renderer) {
this.renderer = renderer;
}
} else {
throw new Error('Provided renderer is not compatible with function or AstRenderer. please change');
}
} else {
if (!this.renderer || this.props.renderer || this.props.rules !== rules || this.props.style !== style) {
this.renderer = new AstRenderer(
{
...renderRules,
...(rules || {}),
},
{
...styles,
...style,
}
);
}
}

if (!this.markdownParser || this.props.markdownit !== markdownit || plugins !== this.props.plugins) {
let md = markdownit;
if (plugins && plugins.length > 0) {
plugins.forEach(plugin => {
md = md.use.apply(md, plugin.toArray());
});
}

this.markdownParser = md;
}
}

/**
*
*/
componentWillMount() {
this.updateSettings(this.props);
}

/**
*
* @param nextProps
*/
componentWillReceiveProps(nextProps) {
this.updateSettings(nextProps);
}

/**
*
* @param children
* @return {string}
*/
getCopyFromChildren(children = this.props.children) {
return children instanceof Array ? children.join('') : children;
}

/**
*
* @return {View}
*/
render() {
const copy = (this.copy = this.getCopyFromChildren());
return parser(copy, this.renderer.render, this.markdownParser);
}
}
export default Markdown;

0 comments on commit 0f386b3

Please sign in to comment.