@@ -34,7 +34,6 @@ max_allowed_length - if set, isURL will not allow URLs longer than the specified
3434
3535*/
3636
37-
3837const default_url_options = {
3938 protocols : [ 'http' , 'https' , 'ftp' ] ,
4039 require_tld : true ,
@@ -71,7 +70,10 @@ export default function isURL(url, options) {
7170 return false ;
7271 }
7372
74- if ( ! options . allow_query_components && ( includes ( url , '?' ) || includes ( url , '&' ) ) ) {
73+ if (
74+ ! options . allow_query_components &&
75+ ( includes ( url , '?' ) || includes ( url , '&' ) )
76+ ) {
7577 return false ;
7678 }
7779
@@ -83,21 +85,33 @@ export default function isURL(url, options) {
8385 split = url . split ( '?' ) ;
8486 url = split . shift ( ) ;
8587
86- split = url . split ( '://' ) ;
87- if ( split . length > 1 ) {
88- protocol = split . shift ( ) . toLowerCase ( ) ;
89- if ( options . require_valid_protocol && options . protocols . indexOf ( protocol ) === - 1 ) {
90- return false ;
88+ // Replaced the 'split("://")' logic with a regex to match the protocol.
89+ // This correctly identifies schemes like `javascript:` which don't use `//`.
90+ const protocol_match = url . match ( / ^ ( [ a - z ] [ a - z 0 - 9 + \- . ] * ) : / i) ;
91+ const hadExplicitProtocol = ! ! protocol_match ;
92+
93+ if ( protocol_match ) {
94+ protocol = protocol_match [ 1 ] . toLowerCase ( ) ;
95+ if (
96+ options . require_valid_protocol &&
97+ options . protocols . indexOf ( protocol ) === - 1
98+ ) {
99+ return false ; // The identified protocol is not in the allowed list.
91100 }
101+ url = url . substring ( protocol_match [ 0 ] . length ) ; // Remove the protocol from the URL string.
92102 } else if ( options . require_protocol ) {
93- return false ;
94- } else if ( url . slice ( 0 , 2 ) === '//' ) {
95- if ( ! options . allow_protocol_relative_urls ) {
103+ return false ; // A protocol was required but not found.
104+ }
105+
106+ // Handle leading '//' only as protocol-relative when there was NO explicit protocol.
107+ // If there was an explicit protocol, '//' is the normal separator
108+ // and should be stripped unconditionally.
109+ if ( url . slice ( 0 , 2 ) === '//' ) {
110+ if ( ! hadExplicitProtocol && ! options . allow_protocol_relative_urls ) {
96111 return false ;
97112 }
98- split [ 0 ] = url . slice ( 2 ) ;
113+ url = url . slice ( 2 ) ; // Remove the '//' from the URL string.
99114 }
100- url = split . join ( '://' ) ;
101115
102116 if ( url === '' ) {
103117 return false ;
0 commit comments