Skip to content

Commit d2bbb80

Browse files
committed
Split email/hashtag/phone/url specs out into separate files from autolinker.spec.ts, and fix issue with hashtag matcher which could match partial hashtags that were too long
1 parent 0747e68 commit d2bbb80

File tree

6 files changed

+1107
-1058
lines changed

6 files changed

+1107
-1058
lines changed

src/matcher/hashtag-matcher.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class HashtagMatcher extends Matcher {
2929
* @protected
3030
* @property {RegExp} matcherRegex
3131
*/
32-
protected matcherRegex = new RegExp( '#[_' + alphaNumericAndMarksCharsStr + ']{1,139}', 'g' );
32+
protected matcherRegex = new RegExp( `#[_${alphaNumericAndMarksCharsStr}]{1,139}(?![_${alphaNumericAndMarksCharsStr}])`, 'g' ); // lookahead used to make sure we don't match something above 139 characters
3333

3434
/**
3535
* The regular expression to use to check the character before a username match to

tests/autolinker-email.spec.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import _ from 'lodash';
2+
import Autolinker from '../src/autolinker';
3+
4+
describe( "Autolinker Email Matching -", () => {
5+
const autolinker = new Autolinker( { newWindow: false } ); // so that target="_blank" is not added to resulting autolinked URLs
6+
7+
8+
it( "should automatically link an email address which is the only text in the string", function() {
9+
let result = autolinker.link( "joe@joe.com" );
10+
11+
expect( result ).toBe( '<a href="mailto:joe@joe.com">joe@joe.com</a>' );
12+
} );
13+
14+
15+
it( "should automatically link email addresses at the start of the string", function() {
16+
let result = autolinker.link( "joe@joe.com is Joe's email" );
17+
18+
expect( result ).toBe( '<a href="mailto:joe@joe.com">joe@joe.com</a> is Joe\'s email' );
19+
} );
20+
21+
22+
it( "should automatically link an email address in the middle of the string", function() {
23+
let result = autolinker.link( "Joe's email is joe@joe.com because it is" );
24+
25+
expect( result ).toBe( 'Joe\'s email is <a href="mailto:joe@joe.com">joe@joe.com</a> because it is' );
26+
} );
27+
28+
29+
it( "should automatically link email addresses at the end of the string", function() {
30+
let result = autolinker.link( "Joe's email is joe@joe.com" );
31+
32+
expect( result ).toBe( 'Joe\'s email is <a href="mailto:joe@joe.com">joe@joe.com</a>' );
33+
} );
34+
35+
36+
it( "should automatically link email addresses with a period in the 'local part'", function() {
37+
let result = autolinker.link( "Joe's email is joe.smith@joe.com" );
38+
39+
expect( result ).toBe( 'Joe\'s email is <a href="mailto:joe.smith@joe.com">joe.smith@joe.com</a>' );
40+
} );
41+
42+
43+
it( "should automatically link fully-capitalized email addresses", function() {
44+
let result = autolinker.link( "Joe's email is JOE@JOE.COM" );
45+
46+
expect( result ).toBe( 'Joe\'s email is <a href="mailto:JOE@JOE.COM">JOE@JOE.COM</a>' );
47+
} );
48+
49+
50+
it( "should properly link an email address in parenthesis", function() {
51+
let result = autolinker.link( "Joe's email is (joe@joe.com)" );
52+
53+
expect( result ).toBe( 'Joe\'s email is (<a href="mailto:joe@joe.com">joe@joe.com</a>)' );
54+
} );
55+
56+
57+
it( "should properly link an email address with underscores", function() {
58+
let result = autolinker.link( "Joe's email is (joe_roe@joe.com)" );
59+
60+
expect( result ).toBe( 'Joe\'s email is (<a href="mailto:joe_roe@joe.com">joe_roe@joe.com</a>)' );
61+
} );
62+
63+
64+
it( "should properly link an email address with an apostrophe", function() {
65+
let result = autolinker.link( "Joe's email is (joe'roe@joe.com)" );
66+
67+
expect( result ).toBe( 'Joe\'s email is (<a href="mailto:joe\'roe@joe.com">joe\'roe@joe.com</a>)' );
68+
} );
69+
70+
71+
it( "should automatically link an email address with accented characters", function() {
72+
let result = autolinker.link( "Joe's email is mañana@mañana.com" );
73+
74+
expect( result ).toBe( 'Joe\'s email is <a href="mailto:mañana@mañana.com">mañana@mañana.com</a>' );
75+
} );
76+
77+
78+
it( "should automatically link an email address with cyrillic characters", function() {
79+
let result = autolinker.link( "Joe's email is Кириллица@Кириллица.com" );
80+
81+
expect( result ).toBe( 'Joe\'s email is <a href="mailto:Кириллица@Кириллица.com">Кириллица@Кириллица.com</a>' );
82+
} );
83+
84+
85+
it( "should NOT automatically link any old word with an @ character in it", function() {
86+
let result = autolinker.link( "Hi there@stuff" );
87+
88+
expect( result ).toBe( 'Hi there@stuff' );
89+
} );
90+
91+
it( "should automatically link an email address with tld matched localpart", function () {
92+
let result = autolinker.link( "My email is busueng.kim@aaa.com" );
93+
94+
expect( result ).toBe( 'My email is <a href="mailto:busueng.kim@aaa.com">busueng.kim@aaa.com</a>');
95+
} );
96+
97+
} );

tests/autolinker-hashtag.spec.ts

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import _ from 'lodash';
2+
import Autolinker from '../src/autolinker';
3+
4+
describe( `Autolinker Hashtag Matching -`, () => {
5+
const autolinker = new Autolinker( { newWindow: false } );
6+
const twitterAutolinker = new Autolinker( { hashtag: 'twitter', newWindow: false } );
7+
const facebookAutolinker = new Autolinker( { hashtag: 'facebook', newWindow: false } );
8+
const instagramAutolinker = new Autolinker( { hashtag: 'instagram', newWindow: false } );
9+
10+
const services = [
11+
{ serviceName: 'twitter', urlPrefix: 'https://twitter.com/hashtag', autolinker: twitterAutolinker },
12+
{ serviceName: 'instagram', urlPrefix: 'https://instagram.com/explore/tags', autolinker: instagramAutolinker },
13+
{ serviceName: 'facebook', urlPrefix: 'https://www.facebook.com/hashtag', autolinker: facebookAutolinker },
14+
];
15+
16+
17+
it( `should NOT autolink hashtags by default for both backward compatibility,
18+
and because we don't know which service (twitter, facebook, etc.) to
19+
point them to`,
20+
() => {
21+
expect( autolinker.link( `#test` ) ).toBe( `#test` );
22+
} );
23+
24+
25+
it( `should NOT autolink hashtags the 'hashtag' cfg is explicitly false`, () => {
26+
const result = Autolinker.link( `#test`, { hashtag: false } );
27+
28+
expect( result ).toBe( `#test` );
29+
} );
30+
31+
32+
describe( 'all services hashtag tests', () => {
33+
34+
services.forEach( ( { serviceName, urlPrefix, autolinker } ) => {
35+
36+
it( `should automatically link hashtags to ${serviceName} when the
37+
'hashtag' option is '${serviceName}'`,
38+
() => {
39+
const result = autolinker.link( `#test` );
40+
41+
expect( result ).toBe( `<a href="${urlPrefix}/test">#test</a>` );
42+
} );
43+
44+
45+
it( `should automatically link hashtags which are part of a full
46+
string when using the ${serviceName} service`,
47+
() => {
48+
const result = autolinker.link( `my hashtag is #test these days` );
49+
50+
expect( result ).toBe( `my hashtag is <a href="${urlPrefix}/test">#test</a> these days` );
51+
} );
52+
53+
54+
it( `should link a hashtag that is up to 139 characters long when
55+
using the ${serviceName} service`,
56+
() => {
57+
const aHashtag = _.repeat( 'a', 139 );
58+
const bHashtag = _.repeat( 'b', 140 ); // too long - don't link
59+
60+
const result = autolinker.link( `#${aHashtag} and #${bHashtag}` );
61+
expect( result ).toBe( `<a href="${urlPrefix}/${aHashtag}">#${aHashtag}</a> and #${bHashtag}` );
62+
} );
63+
64+
65+
it( `should automatically link a hashtag with underscores when using
66+
the ${serviceName} service`,
67+
() => {
68+
const result = autolinker.link( `Yay, #hello_world` );
69+
expect( result ).toBe( `Yay, <a href="${urlPrefix}/hello_world">#hello_world</a>` );
70+
} );
71+
72+
73+
it( `should automatically link a hashtag with accented characters
74+
when using the ${serviceName} service`,
75+
() => {
76+
const result = autolinker.link( `Yay, #mañana` );
77+
expect( result ).toBe( `Yay, <a href="${urlPrefix}/mañana">#mañana</a>` );
78+
} );
79+
80+
81+
it( `should automatically link a hashtag with cyrillic characters
82+
when using the ${serviceName} service`,
83+
() => {
84+
const result = autolinker.link( `Yay, #Кириллица` );
85+
expect( result ).toBe( `Yay, <a href="${urlPrefix}/Кириллица">#Кириллица</a>` );
86+
} );
87+
88+
89+
it( `should NOT automatically link a hashtag when the '#' belongs to
90+
part of another string when using the ${serviceName} service`,
91+
() => {
92+
const result = autolinker.link( `test as#df test` );
93+
94+
expect( result ).toBe( `test as#df test` );
95+
} );
96+
97+
98+
it( `should NOT automatically link a hashtag that is actually a
99+
named anchor within a URL when using the ${serviceName} service`,
100+
() => {
101+
const result = autolinker.link( `http://google.com/#link` );
102+
103+
expect( result ).toBe( `<a href="http://google.com/#link">google.com/#link</a>` );
104+
} );
105+
106+
107+
it( `should NOT automatically link a hashtag that is actually a
108+
named anchor within a URL **when URL linking is turned off**
109+
when using the ${serviceName} service`,
110+
() => {
111+
const noUrlTwitterHashtagAutolinker = new Autolinker( {
112+
urls: false,
113+
hashtag: 'twitter',
114+
newWindow: false
115+
} );
116+
const result = noUrlTwitterHashtagAutolinker.link( `http://google.com/#link` );
117+
118+
expect( result ).toBe( `http://google.com/#link` );
119+
} );
120+
121+
} );
122+
123+
} );
124+
125+
} );

tests/autolinker-phone.spec.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import _ from 'lodash';
2+
import Autolinker from '../src/autolinker';
3+
4+
describe( "Autolinker Phone Number Matching -", () => {
5+
const autolinker = new Autolinker( { newWindow: false } ); // so that target="_blank" is not added to resulting autolinked URLs
6+
7+
it( "should automatically link an in-country phone number", function() {
8+
expect( autolinker.link( "(555)666-7777" ) ).toBe( '<a href="tel:5556667777">(555)666-7777</a>' );
9+
expect( autolinker.link( "(555) 666-7777" ) ).toBe( '<a href="tel:5556667777">(555) 666-7777</a>' );
10+
expect( autolinker.link( "555-666-7777" ) ).toBe( '<a href="tel:5556667777">555-666-7777</a>' );
11+
expect( autolinker.link( "555 666 7777" ) ).toBe( '<a href="tel:5556667777">555 666 7777</a>' );
12+
expect( autolinker.link( "555.666.7777" ) ).toBe( '<a href="tel:5556667777">555.666.7777</a>' );
13+
} );
14+
15+
16+
it( "should automatically link an international phone number", function() {
17+
expect( autolinker.link( "+1-541-754-3010" ) ).toBe( '<a href="tel:+15417543010">+1-541-754-3010</a>' );
18+
expect( autolinker.link( "1-541-754-3010" ) ).toBe( '<a href="tel:15417543010">1-541-754-3010</a>' );
19+
expect( autolinker.link( "1 (541) 754-3010" ) ).toBe( '<a href="tel:15417543010">1 (541) 754-3010</a>' );
20+
expect( autolinker.link( "1.541.754.3010" ) ).toBe( '<a href="tel:15417543010">1.541.754.3010</a>' );
21+
expect( autolinker.link( "+43 5 1766 1000" ) ).toBe( '<a href="tel:+43517661000">+43 5 1766 1000</a>' );
22+
expect( autolinker.link( "+381 38 502 456" ) ).toBe( '<a href="tel:+38138502456">+381 38 502 456</a>' );
23+
expect( autolinker.link( "+38755233976" ) ).toBe( '<a href="tel:+38755233976">+38755233976</a>' );
24+
expect( autolinker.link( "+852 2846 6433" ) ).toBe( '<a href="tel:+85228466433">+852 2846 6433</a>' );
25+
} );
26+
27+
28+
it( "should automatically link a phone number that is completely surrounded by parenthesis", function() {
29+
let result = autolinker.link( "((555) 666-7777)" );
30+
expect( result ).toBe( '(<a href="tel:5556667777">(555) 666-7777</a>)' );
31+
} );
32+
33+
34+
it( "should automatically link a phone number contained in a larger string", function() {
35+
let result = autolinker.link( "Here's my number: (555)666-7777, so call me maybe?" );
36+
expect( result ).toBe( 'Here\'s my number: <a href=\"tel:5556667777\">(555)666-7777</a>, so call me maybe?' );
37+
} );
38+
39+
40+
it( "should automatically link a phone number surrounded by parenthesis contained in a larger string", function() {
41+
let result = autolinker.link( "Here's my number ((555)666-7777), so call me maybe?" );
42+
expect( result ).toBe( 'Here\'s my number (<a href=\"tel:5556667777\">(555)666-7777</a>), so call me maybe?' );
43+
} );
44+
45+
46+
it( "should NOT automatically link a phone number when there are no delimiters, since we don't know for sure if this is a phone number or some other number", function() {
47+
expect( autolinker.link( "5556667777" ) ).toBe( '5556667777' );
48+
expect( autolinker.link( "15417543010" ) ).toBe( '15417543010' );
49+
} );
50+
51+
it( "should NOT automatically link numbers when there are non-space empty characters (such as newlines) in between", function() {
52+
expect( autolinker.link( "555 666 7777" ) ).toBe( '555 666 7777' );
53+
expect( autolinker.link( "555 666 7777" ) ).toBe( '555 666 7777' );
54+
expect( autolinker.link( "555\n666 7777" ) ).toBe( '555\n666 7777' );
55+
} );
56+
57+
58+
it( "should automatically link numbers when there are extensions with ,<numbers>#", function() {
59+
expect( autolinker.link( "555 666 7777,234523#,23453#" ) ).toBe( '<a href="tel:5556667777,234523#,23453#">555 666 7777,234523#,23453#</a>' );
60+
expect( autolinker.link( "1-555-666-7777,234523#" ) ).toBe( '<a href="tel:15556667777,234523#">1-555-666-7777,234523#</a>' );
61+
expect( autolinker.link( "+1-555-666-7777,234523#" ) ).toBe( '<a href="tel:+15556667777,234523#">+1-555-666-7777,234523#</a>' );
62+
expect( autolinker.link( "+1-555-666-7777,234523,233" ) ).toBe( '<a href="tel:+15556667777,234523,233">+1-555-666-7777,234523,233</a>' );
63+
expect( autolinker.link( "+22016350659,;,55#;;234 , 3334443323" ) ).toBe( '<a href="tel:+22016350659,;,55#;;234">+22016350659,;,55#;;234</a> , 3334443323' );
64+
} );
65+
66+
67+
it( "should NOT automatically link numbers when there are extensions with ,<numbers># followed by a number", function() {
68+
expect( autolinker.link( "+1-555-666-7777,234523#233" ) ).toBe( '+1-555-666-7777,234523#233' );
69+
expect( autolinker.link( "+1-555-666-7777,234523#abc" ) ).toBe( '<a href="tel:+15556667777,234523#">+1-555-666-7777,234523#</a>abc' );
70+
expect( autolinker.link( "+1-555-666-7777,234523#,234523#abc" ) ).toBe( '<a href="tel:+15556667777,234523#,234523#">+1-555-666-7777,234523#,234523#</a>abc' );
71+
} );
72+
73+
} );

0 commit comments

Comments
 (0)