@@ -28,6 +28,7 @@ import {
28
28
PLUS ,
29
29
POUND ,
30
30
PROTOCOL ,
31
+ MAILTO ,
31
32
QUERY ,
32
33
SLASH ,
33
34
UNDERSCORE ,
@@ -45,6 +46,7 @@ import {
45
46
} from './tokens/text' ;
46
47
47
48
import {
49
+ MAILTOEMAIL ,
48
50
EMAIL ,
49
51
NL as MNL ,
50
52
TEXT ,
@@ -58,42 +60,46 @@ let S_START = makeState();
58
60
59
61
// Intermediate states for URLs. Note that domains that begin with a protocol
60
62
// are treated slighly differently from those that don't.
61
- let S_PROTOCOL = makeState ( ) ; // e.g., 'http:'
62
- let S_PROTOCOL_SLASH = makeState ( ) ; // e.g., '/', 'http:/''
63
- let S_PROTOCOL_SLASH_SLASH = makeState ( ) ; // e.g., '//', 'http://'
64
- let S_DOMAIN = makeState ( ) ; // parsed string ends with a potential domain name (A)
65
- let S_DOMAIN_DOT = makeState ( ) ; // (A) domain followed by DOT
66
- let S_TLD = makeState ( URL ) ; // (A) Simplest possible URL with no query string
67
- let S_TLD_COLON = makeState ( ) ; // (A) URL followed by colon (potential port number here)
68
- let S_TLD_PORT = makeState ( URL ) ; // TLD followed by a port number
69
- let S_URL = makeState ( URL ) ; // Long URL with optional port and maybe query string
70
- let S_URL_NON_ACCEPTING = makeState ( ) ; // URL followed by some symbols (will not be part of the final URL)
71
- let S_URL_OPENBRACE = makeState ( ) ; // URL followed by {
72
- let S_URL_OPENBRACKET = makeState ( ) ; // URL followed by [
73
- let S_URL_OPENANGLEBRACKET = makeState ( ) ; // URL followed by <
74
- let S_URL_OPENPAREN = makeState ( ) ; // URL followed by (
75
- let S_URL_OPENBRACE_Q = makeState ( URL ) ; // URL followed by { and some symbols that the URL can end it
76
- let S_URL_OPENBRACKET_Q = makeState ( URL ) ; // URL followed by [ and some symbols that the URL can end it
77
- let S_URL_OPENANGLEBRACKET_Q = makeState ( URL ) ; // URL followed by < and some symbols that the URL can end it
78
- let S_URL_OPENPAREN_Q = makeState ( URL ) ; // URL followed by ( and some symbols that the URL can end it
79
- let S_URL_OPENBRACE_SYMS = makeState ( ) ; // S_URL_OPENBRACE_Q followed by some symbols it cannot end it
80
- let S_URL_OPENBRACKET_SYMS = makeState ( ) ; // S_URL_OPENBRACKET_Q followed by some symbols it cannot end it
81
- let S_URL_OPENANGLEBRACKET_SYMS = makeState ( ) ; // S_URL_OPENANGLEBRACKET_Q followed by some symbols it cannot end it
82
- let S_URL_OPENPAREN_SYMS = makeState ( ) ; // S_URL_OPENPAREN_Q followed by some symbols it cannot end it
83
- let S_EMAIL_DOMAIN = makeState ( ) ; // parsed string starts with local email info + @ with a potential domain name (C)
84
- let S_EMAIL_DOMAIN_DOT = makeState ( ) ; // (C) domain followed by DOT
85
- let S_EMAIL = makeState ( EMAIL ) ; // (C) Possible email address (could have more tlds)
86
- let S_EMAIL_COLON = makeState ( ) ; // (C) URL followed by colon (potential port number here)
87
- let S_EMAIL_PORT = makeState ( EMAIL ) ; // (C) Email address with a port
88
- let S_LOCALPART = makeState ( ) ; // Local part of the email address
89
- let S_LOCALPART_AT = makeState ( ) ; // Local part of the email address plus @
90
- let S_LOCALPART_DOT = makeState ( ) ; // Local part of the email address plus '.' (localpart cannot end in .)
91
- let S_NL = makeState ( MNL ) ; // single new line
63
+ let S_PROTOCOL = makeState ( ) ; // e.g., 'http:'
64
+ let S_MAILTO = makeState ( ) ; // 'mailto:'
65
+ let S_PROTOCOL_SLASH = makeState ( ) ; // e.g., '/', 'http:/''
66
+ let S_PROTOCOL_SLASH_SLASH = makeState ( ) ; // e.g., '//', 'http://'
67
+ let S_DOMAIN = makeState ( ) ; // parsed string ends with a potential domain name (A)
68
+ let S_DOMAIN_DOT = makeState ( ) ; // (A) domain followed by DOT
69
+ let S_TLD = makeState ( URL ) ; // (A) Simplest possible URL with no query string
70
+ let S_TLD_COLON = makeState ( ) ; // (A) URL followed by colon (potential port number here)
71
+ let S_TLD_PORT = makeState ( URL ) ; // TLD followed by a port number
72
+ let S_URL = makeState ( URL ) ; // Long URL with optional port and maybe query string
73
+ let S_URL_NON_ACCEPTING = makeState ( ) ; // URL followed by some symbols (will not be part of the final URL)
74
+ let S_URL_OPENBRACE = makeState ( ) ; // URL followed by {
75
+ let S_URL_OPENBRACKET = makeState ( ) ; // URL followed by [
76
+ let S_URL_OPENANGLEBRACKET = makeState ( ) ; // URL followed by <
77
+ let S_URL_OPENPAREN = makeState ( ) ; // URL followed by (
78
+ let S_URL_OPENBRACE_Q = makeState ( URL ) ; // URL followed by { and some symbols that the URL can end it
79
+ let S_URL_OPENBRACKET_Q = makeState ( URL ) ; // URL followed by [ and some symbols that the URL can end it
80
+ let S_URL_OPENANGLEBRACKET_Q = makeState ( URL ) ; // URL followed by < and some symbols that the URL can end it
81
+ let S_URL_OPENPAREN_Q = makeState ( URL ) ; // URL followed by ( and some symbols that the URL can end it
82
+ let S_URL_OPENBRACE_SYMS = makeState ( ) ; // S_URL_OPENBRACE_Q followed by some symbols it cannot end it
83
+ let S_URL_OPENBRACKET_SYMS = makeState ( ) ; // S_URL_OPENBRACKET_Q followed by some symbols it cannot end it
84
+ let S_URL_OPENANGLEBRACKET_SYMS = makeState ( ) ; // S_URL_OPENANGLEBRACKET_Q followed by some symbols it cannot end it
85
+ let S_URL_OPENPAREN_SYMS = makeState ( ) ; // S_URL_OPENPAREN_Q followed by some symbols it cannot end it
86
+ let S_EMAIL_DOMAIN = makeState ( ) ; // parsed string starts with local email info + @ with a potential domain name (C)
87
+ let S_EMAIL_DOMAIN_DOT = makeState ( ) ; // (C) domain followed by DOT
88
+ let S_EMAIL = makeState ( EMAIL ) ; // (C) Possible email address (could have more tlds)
89
+ let S_EMAIL_COLON = makeState ( ) ; // (C) URL followed by colon (potential port number here)
90
+ let S_EMAIL_PORT = makeState ( EMAIL ) ; // (C) Email address with a port
91
+ let S_MAILTO_EMAIL = makeState ( MAILTOEMAIL ) ; // Email that begins with the mailto prefix (D)
92
+ let S_MAILTO_EMAIL_NON_ACCEPTING = makeState ( ) ; // (D) Followed by some non-query string chars
93
+ let S_LOCALPART = makeState ( ) ; // Local part of the email address
94
+ let S_LOCALPART_AT = makeState ( ) ; // Local part of the email address plus @
95
+ let S_LOCALPART_DOT = makeState ( ) ; // Local part of the email address plus '.' (localpart cannot end in .)
96
+ let S_NL = makeState ( MNL ) ; // single new line
92
97
93
98
// Make path from start to protocol (with '//')
94
99
S_START
95
100
. on ( TNL , S_NL )
96
101
. on ( PROTOCOL , S_PROTOCOL )
102
+ . on ( MAILTO , S_MAILTO )
97
103
. on ( SLASH , S_PROTOCOL_SLASH ) ;
98
104
99
105
S_PROTOCOL . on ( SLASH , S_PROTOCOL_SLASH ) ;
@@ -255,6 +261,23 @@ S_URL_NON_ACCEPTING.on(qsNonAccepting, S_URL_NON_ACCEPTING);
255
261
// Note: We are not allowing '/' in email addresses since this would interfere
256
262
// with real URLs
257
263
264
+ // For addresses with the mailto prefix
265
+ // 'mailto:' followed by anything sane is a valid email
266
+ S_MAILTO
267
+ . on ( TLD , S_MAILTO_EMAIL )
268
+ . on ( DOMAIN , S_MAILTO_EMAIL )
269
+ . on ( NUM , S_MAILTO_EMAIL )
270
+ . on ( LOCALHOST , S_MAILTO_EMAIL ) ;
271
+
272
+ // Greedily get more potential valid email values
273
+ S_MAILTO_EMAIL
274
+ . on ( qsAccepting , S_MAILTO_EMAIL )
275
+ . on ( qsNonAccepting , S_MAILTO_EMAIL_NON_ACCEPTING ) ;
276
+ S_MAILTO_EMAIL_NON_ACCEPTING
277
+ . on ( qsAccepting , S_MAILTO_EMAIL )
278
+ . on ( qsNonAccepting , S_MAILTO_EMAIL_NON_ACCEPTING ) ;
279
+
280
+ // For addresses without the mailto prefix
258
281
// Tokens allowed in the localpart of the email
259
282
let localpartAccepting = [
260
283
DOMAIN ,
0 commit comments