diff --git a/src/Linkify/Linkify.js b/src/Linkify/Linkify.js index 8d8d215..71a72a0 100644 --- a/src/Linkify/Linkify.js +++ b/src/Linkify/Linkify.js @@ -1,19 +1,49 @@ import React from 'react'; -import styled from 'styled-components'; -const Container = styled.span` - a { - color: inherit; - text-decoration: underline; - } -`; +const URL_REGEX = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/gi; -const REGEX = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi; +const Link = ({ href, linkStyle }) => ( + + {href} + +); -const parse = string => string.replace(REGEX, url => `${url}`); +const linkify = ({ children, linkStyle = {} }) => + React.Children.map(children, child => { + if (!child) return null; -const Linkify = props => ( - -); + if (typeof child === 'string') { + const matches = child.match(URL_REGEX); + + if (!matches) { + return child; + } + + // Clone the string for manipulation + let string = `${child}`; + + // Run through the url matches to create our array of string parts and Link components + const stringParts = matches.reduce((parts, url) => { + const urlStartIndex = string.indexOf(url); + const partBeforeUrl = string.substring(0, urlStartIndex); + parts.push(partBeforeUrl, ); + string = string.substring(urlStartIndex + url.length); + return parts; + }, []); + + // Add any leftovers after the last url + return [...stringParts, string]; + } + + return linkify({ children: child.props.children, linkStyle }); + }); -export default Linkify; +export default props => linkify(props); diff --git a/src/Linkify/Linkify.mdx b/src/Linkify/Linkify.mdx index 4532c03..1b775b4 100644 --- a/src/Linkify/Linkify.mdx +++ b/src/Linkify/Linkify.mdx @@ -12,7 +12,15 @@ Automatically parse links contained in a body of text. ## Example - - Checkout http://google.com. Another one that is not that great is http://bing.com. - + {() => { + const testEvaluatedUrl = 'https://www.facebook.com/heydoctor.co'; + return ( + +
+ Checkout http://google.com. Another one that's not so great is http://bing.com. You could also checkout duckduckgo.com if you're into that whole privacy thing. {}} alt="hacker" /> Oh, and you should also check out https://heydoctor.co. I wonder if nested Linkify works {testEvaluatedUrl} +
+
+ ); + }}
diff --git a/src/Linkify/Linkify.spec.js b/src/Linkify/Linkify.spec.js new file mode 100644 index 0000000..55cec18 --- /dev/null +++ b/src/Linkify/Linkify.spec.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { renderWithTheme } from '../../test/utils'; +import Linkify from './Linkify'; + +describe('Linkify', () => { + test('converts links to anchor tags', () => { + const component = renderWithTheme(Hello! https://google.com is a cool site.); + + expect(component).toMatchSnapshot(); + }); + + test('escapes HTML entities', () => { + const component = renderWithTheme( + {` {}} alt="hacker" />heheh got hacked`} + ); + + expect(component).toMatchSnapshot(); + }); + + test('can receive linkStyle', () => { + const component = renderWithTheme( + Hello! https://google.com is a cool site. + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/Linkify/__snapshots__/Linkify.spec.js.snap b/src/Linkify/__snapshots__/Linkify.spec.js.snap new file mode 100644 index 0000000..dfbd4ad --- /dev/null +++ b/src/Linkify/__snapshots__/Linkify.spec.js.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Linkify can receive linkStyle 1`] = ` +Array [ + "Hello! ", + + https://google.com + , + " is a cool site.", +] +`; + +exports[`Linkify converts links to anchor tags 1`] = ` +Array [ + "Hello! ", + + https://google.com + , + " is a cool site.", +] +`; + +exports[`Linkify escapes HTML entities 1`] = `" {}} alt=\\"hacker\\" />heheh got hacked"`;