react-anchorify-text
Version:
React component which render text with anchored url(s)
61 lines (53 loc) • 1.66 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import LinkifyIt from 'linkify-it';
import tlds from 'tlds';
class AnchorifyText extends React.Component {
constructor(props) {
super(props);
}
render() {
let content = this.anchorify(this.props.text);
return (
<span>{content}</span>
);
}
anchorify(text) {
const { linkify, children, target, nonUrlPartsRenderer } = this.props;
const matches = linkify.match(text);
if (matches === null){
return nonUrlPartsRenderer(text);
}
let last = 0;
const result = [];
matches.forEach((match, i) => {
const keyBefore = 'anchorify-text-before' + i;
const keyMatch = 'anchorify-text-match' + i;
if (last < match.index) {
result.push(<span key={keyBefore}>{nonUrlPartsRenderer(text.slice(last, match.index))}</span>);
}
if (React.Children.count(children) === 1) {
result.push(React.cloneElement(children, {url: match.url, key: keyMatch, match: match}));
} else {
result.push(<a key={keyMatch} href={match.url} target={target}>{match.raw}</a>);
}
last = match.lastIndex;
});
if (last < text.length) {
result.push(<span key={'anchorify-text-last'}>{nonUrlPartsRenderer(text.slice(last))}</span>);
}
return result;
}
}
AnchorifyText.propTypes = {
text: PropTypes.string.isRequired,
linkify: PropTypes.object,
target: PropTypes.string,
nonUrlPartsRenderer: PropTypes.func,
};
AnchorifyText.defaultProps = {
linkify: new LinkifyIt().tlds(tlds),
target: '_blank',
nonUrlPartsRenderer: (text) => text,
};
export default AnchorifyText;