2424
2525const  ReplacementTracker  =  require ( './replacement-tracker' ) , 
2626
27-     REGEX_EXTRACT_VARS  =  / { { [ ^ { } ] * [ . : / ? # @ & \] ] [ ^ { } ] * } } / g, 
27+     REGEX_ALL_BACKSLASHES  =  / \\ / g, 
28+     REGEX_LEADING_SLASHES  =  / ^ \/ + / , 
29+     REGEX_ALL_VARIABLES  =  / { { [ ^ { } ] * [ . : / ? # @ & \] ] [ ^ { } ] * } } / g, 
2830
2931    HASH_SEPARATOR  =  '#' , 
3032    PATH_SEPARATOR  =  '/' , 
@@ -35,8 +37,10 @@ const ReplacementTracker = require('./replacement-tracker'),
3537    PROTOCOL_SEPARATOR  =  '://' , 
3638    AUTH_SEGMENTS_SEPARATOR  =  ':' , 
3739    QUERY_SEGMENTS_SEPARATOR  =  '&' , 
38-     PROTOCOL_SEPARATOR_WITH_BACKSLASH  =  ':\\\\' , 
3940
41+     E  =  '' , 
42+     STRING  =  'string' , 
43+     FILE_PROTOCOL  =  'file' , 
4044    SAFE_REPLACE_CHAR  =  '_' , 
4145    CLOSING_SQUARE_BRACKET  =  ']' , 
4246    URL_PROPERTIES_ORDER  =  [ 'protocol' ,  'auth' ,  'host' ,  'port' ,  'path' ,  'query' ,  'hash' ] ; 
@@ -52,7 +56,7 @@ const ReplacementTracker = require('./replacement-tracker'),
5256 * @returns  {String } Normalized string 
5357 */ 
5458function  normalizeVariables  ( str ,  replacements )  { 
55-     let  normalizedString  =  '' , 
59+     let  normalizedString  =  E , 
5660        pointer  =  0 ,  // pointer till witch the string is normalized 
5761        variable , 
5862        match , 
@@ -61,7 +65,7 @@ function normalizeVariables (str, replacements) {
6165    // find all the instances of {{<variable>}} which includes reserved chars 
6266    // "Hello {{user#name}}!!!" 
6367    //  ↑ (pointer = 0) 
64-     while  ( ( match  =  REGEX_EXTRACT_VARS . exec ( str ) )  !==  null )  { 
68+     while  ( ( match  =  REGEX_ALL_VARIABLES . exec ( str ) )  !==  null )  { 
6569        // {{user#name}} 
6670        variable  =  match [ 0 ] ; 
6771
@@ -154,12 +158,14 @@ function parse (urlString) {
154158        } , 
155159        replacements  =  new  ReplacementTracker ( ) , 
156160        pointer  =  0 , 
161+         protocol , 
162+         _length , 
157163        length , 
158164        index , 
159165        port ; 
160166
161167    // bail out if input string is empty 
162-     if  ( ! ( urlString  &&  typeof  urlString  ===  'string' ) )  { 
168+     if  ( ! ( urlString  &&  typeof  urlString  ===  STRING ) )  { 
163169        return  parsedUrl ; 
164170    } 
165171
@@ -191,32 +197,34 @@ function parse (urlString) {
191197    } 
192198
193199    // 3. url.protocol 
200+     urlString  =  urlString . replace ( REGEX_ALL_BACKSLASHES ,  PATH_SEPARATOR ) ;  // sanitize slashes 
201+ 
202+     // @todo  support `protocol:host/path` and `protocol:/host/path` 
194203    if  ( ( index  =  urlString . indexOf ( PROTOCOL_SEPARATOR ) )  !==  - 1 )  { 
195204        // extract from the front 
196-         url . protocol . value  =  urlString . slice ( 0 ,  index ) ; 
205+         url . protocol . value  =  protocol   =   urlString . slice ( 0 ,  index ) ; 
197206        url . protocol . beginIndex  =  pointer ; 
198207        url . protocol . endIndex  =  pointer  +  index ; 
199208
200209        urlString  =  urlString . slice ( index  +  3 ) ; 
201210        length  -=  index  +  3 ; 
202211        pointer  +=  index  +  3 ; 
203212    } 
204-     // protocol can be separated using :\\ as well 
205-     else  if  ( ( index  =  urlString . indexOf ( PROTOCOL_SEPARATOR_WITH_BACKSLASH ) )  !==  - 1 )  { 
206-         // extract from the front 
207-         url . protocol . value  =  urlString . slice ( 0 ,  index ) ; 
208-         url . protocol . beginIndex  =  pointer ; 
209-         url . protocol . endIndex  =  pointer  +  index ; 
210213
211-         urlString  =  urlString . slice ( index  +  3 ) ; 
212-         length  -=  index  +  3 ; 
213-         pointer  +=  index  +  3 ; 
214-     } 
214+     // special handling for leading slashes e.g, http:///example.com 
215+     _length  =  length ;  // length with leading slashes 
215216
216-     // 4. url.path 
217-     urlString  =  urlString . replace ( / \\ / g,  '/' ) ;  // sanitize path 
218-     urlString  =  urlString . replace ( / ^ \/ + / ,  '' ) ;  // remove leading slashes 
217+     urlString  =  urlString . replace ( REGEX_LEADING_SLASHES , 
218+         ( protocol  &&  protocol . toLowerCase ( )  ===  FILE_PROTOCOL )  ?
219+             // file:////path -> file:///path 
220+             PATH_SEPARATOR  :
221+             // protocol:////host/path -> protocol://host/path 
222+             E ) ; 
219223
224+     length  =  urlString . length ;  // length without slashes 
225+     pointer  +=  _length  -  length ;  // update pointer 
226+ 
227+     // 4. url.path 
220228    if  ( ( index  =  urlString . indexOf ( PATH_SEPARATOR ) )  !==  - 1 )  { 
221229        // extract from the back 
222230        url . path . value  =  urlString . slice ( index  +  1 ) . split ( PATH_SEPARATOR ) ; 
0 commit comments