diff --git a/lib/__tests__/__snapshots__/text.tsx.snap b/lib/__tests__/__snapshots__/text.tsx.snap index 1a5181c8..133fe4b6 100644 --- a/lib/__tests__/__snapshots__/text.tsx.snap +++ b/lib/__tests__/__snapshots__/text.tsx.snap @@ -9,7 +9,6 @@ Array [ > http://google.com , - "", ], Please go to @@ -18,7 +17,6 @@ Array [ > http://google.com - , ] `; @@ -27,13 +25,11 @@ exports[`text linkify attach link on nested elements containing links 1`] = ` Please go to - http://google.com - lalala @@ -47,7 +43,6 @@ exports[`text linkify attach link on simple elements containing links 1`] = ` > http://google.com - `; @@ -59,7 +54,6 @@ Array [ > http://google.com , - "", ] `; @@ -71,7 +65,6 @@ Array [ > http://www.rumtoast.com/5444/line群組行動條碼邀請-一定要關掉,不然駭客會入侵 , - "", ] `; @@ -90,7 +83,58 @@ Array [ 駭客會入侵 , - "", +] +`; + +exports[`text linkify parses half-width brackets correctly 1`] = ` +Array [ + + http://foo.com/blah_(a)_(b) + , + " (", + + http://foo.com/blah_(a)_(b) + , + ") ", + + http://foo.com/blah_(a)_(b) + , + ")", +] +`; + +exports[`text linkify parses full-width brackets correctly 1`] = ` +Array [ + + http://foo.com/blah_(a)_(b) + , + " (", + + http://foo.com/blah_(a)_(b) + , + ") ", + + http://foo.com/blah_(a)_(b) + , + ")", ] `; @@ -103,7 +147,6 @@ Array [ > http://google.com , - "", ] `; diff --git a/lib/__tests__/text.tsx b/lib/__tests__/text.tsx index 66bb69c6..ff906d94 100644 --- a/lib/__tests__/text.tsx +++ b/lib/__tests__/text.tsx @@ -73,6 +73,28 @@ describe('text', () => { }) ).toMatchSnapshot(); }); + + it('parses half-width brackets correctly', () => { + expect( + linkify( + 'http://foo.com/blah_(a)_(b) (http://foo.com/blah_(a)_(b)) http://foo.com/blah_(a)_(b))', + { + props: { target: '_blank' }, + } + ) + ).toMatchSnapshot(); + }); + + it('parses full-width brackets correctly', () => { + expect( + linkify( + 'http://foo.com/blah_(a)_(b) (http://foo.com/blah_(a)_(b)) http://foo.com/blah_(a)_(b))', + { + props: { target: '_blank' }, + } + ) + ).toMatchSnapshot(); + }); }); describe('nl2br', () => { diff --git a/lib/text.tsx b/lib/text.tsx index 5d715a2f..93b0d713 100644 --- a/lib/text.tsx +++ b/lib/text.tsx @@ -2,6 +2,7 @@ import React, { CSSProperties } from 'react'; import { gql } from 'graphql-tag'; import { withStyles, WithStyles, createStyles } from '@material-ui/core/styles'; import { HighlightFieldsFragment } from 'typegen/graphql'; +import { tokenize } from 'linkifyjs'; const BREAK = { $$BREAK: true } as const; @@ -105,12 +106,10 @@ function shortenUrl(s: string, maxLength: number) { function flatternPureStrings(tokens: React.ReactChild[]) { return tokens.every(token => typeof token === 'string') - ? tokens.join() + ? tokens.join('') : tokens; } -const urlRegExp = /(https?:\/\/\S+)/; - /** * Wrap around hyperlinks inside a react element or string. * @@ -127,13 +126,13 @@ export function linkify( return traverseForStrings(elem, str => { if (!str) return str; - const tokenized = str.split(urlRegExp).map((s, i) => - s.match(urlRegExp) ? ( - - {shortenUrl(s, maxLength)} + const tokenized = tokenize(str).map((token, i) => + token.isLink ? ( + + {shortenUrl(token.v, maxLength)} ) : ( - s + token.toString() ) ); diff --git a/package-lock.json b/package-lock.json index a73b3896..5adfb6d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "isomorphic-unfetch": "^3.0.0", "js-cookie": "^3.0.1", "json-url": "^2.6.0", + "linkifyjs": "^4.1.3", "lodash": "^4.17.19", "marked": "^4.1.1", "next": "^9.3.2", @@ -22153,6 +22154,11 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkifyjs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.3.tgz", + "integrity": "sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==" + }, "node_modules/listr2": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", @@ -50674,6 +50680,11 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "linkifyjs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.3.tgz", + "integrity": "sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==" + }, "listr2": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", diff --git a/package.json b/package.json index 9a0db2e0..8b897f0e 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "isomorphic-unfetch": "^3.0.0", "js-cookie": "^3.0.1", "json-url": "^2.6.0", + "linkifyjs": "^4.1.3", "lodash": "^4.17.19", "marked": "^4.1.1", "next": "^9.3.2",