import React, { useCallback, useMemo } from 'react' import { Link } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' import PropTypes from 'prop-types' const useStyles = makeStyles( (theme) => ({ link: { textDecoration: 'none', color: theme.palette.primary.main, }, }), { name: 'RaLink' } ) const Linkify = ({ text, ...rest }) => { const classes = useStyles() const linkify = useCallback((text) => { const urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/gi return [...text.matchAll(urlRegex)] }, []) const parse = useCallback(() => { const matches = linkify(text) if (matches.length === 0) return text const elements = [] let lastIndex = 0 matches.forEach((match, index) => { // Push text located before matched string if (match.index > lastIndex) { elements.push(text.substring(lastIndex, match.index)) } const href = match[0] // Push Link component elements.push( {href} ) lastIndex = match.index + href.length }) // Push remaining text if (text.length > lastIndex) { elements.push( ) } return elements.length === 1 ? elements[0] : elements }, [linkify, text, rest, classes.link]) const parsedText = useMemo(() => parse(), [parse]) return <>{parsedText} } Linkify.propTypes = { text: PropTypes.string, } export default React.memo(Linkify)