@@ -93,8 +93,73 @@ const defaultDelimiter = "/"
93
93
var escapeRegexp = regexp2 .MustCompile ("([.+*?=^!:${}()[\\ ]|/\\ \\ ])" , regexp2 .None )
94
94
var tokenRegexp = regexp2 .MustCompile ("\\ ((?!\\ ?)" , regexp2 .None )
95
95
96
- func normalize (str string ) string {
97
- t := transform .Chain (norm .NFC , runes .Remove (runes .In (unicode .Mn )), norm .NFC )
96
+ // EncodeURIComponent encodes a text string as a valid component of a Uniform
97
+ // Resource Identifier (URI).
98
+ func EncodeURIComponent (str string ) string {
99
+ r := url .QueryEscape (str )
100
+ r = strings .Replace (r , "+" , "%20" , - 1 )
101
+ return r
102
+ }
103
+
104
+ // Gets the unencoded version of an encoded component of a Uniform Resource
105
+ // Identifier (URI).
106
+ func DecodeURIComponent (str string ) string {
107
+ r , err := url .QueryUnescape (str )
108
+ if err != nil {
109
+ panic (err )
110
+ }
111
+ return r
112
+ }
113
+
114
+ // Encodes a text string as a valid Uniform Resource Identifier (URI)
115
+ func encodeURI (str string ) string {
116
+ excludes := ";/?:@&=+$,#"
117
+ arr := strings .Split (str , "" )
118
+ result := ""
119
+ for _ , v := range arr {
120
+ if strings .Contains (excludes , v ) {
121
+ result += v
122
+ } else {
123
+ result += EncodeURIComponent (v )
124
+ }
125
+ }
126
+ return result
127
+ }
128
+
129
+ // Gets the unencoded version of an encoded Uniform Resource Identifier (URI).
130
+ func decodeURI (str string ) string {
131
+ magicWords := "1@X#y!Z" // not a good idea
132
+ excludes := []string {"%3B" , "%2F" , "%3F" , "%3A" , "%40" , "%26" , "%3D" , "%2B" , "%24" , "%2C" , "%23" }
133
+ r := regexp2 .MustCompile (strings .Join (excludes , "|" ), regexp2 .None )
134
+
135
+ str , _ = r .ReplaceFunc (str , func (m regexp2.Match ) string {
136
+ return strings .Replace (m .String (), "%" , magicWords , - 1 )
137
+ }, - 1 , - 1 )
138
+
139
+ str = decodeURIComponent (str , nil )
140
+
141
+ for i , v := range excludes {
142
+ excludes [i ] = magicWords + strings .TrimPrefix (v , "%" )
143
+ }
144
+ r = regexp2 .MustCompile (strings .Join (excludes , "|" ), regexp2 .None )
145
+
146
+ str , _ = r .ReplaceFunc (str , func (m regexp2.Match ) string {
147
+ return strings .Replace (m .String (), magicWords , "%" , - 1 )
148
+ }, - 1 , - 1 )
149
+
150
+ return str
151
+ }
152
+
153
+ // Returns the String value result of normalizing the string into the normalization form
154
+ // named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
155
+ // param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
156
+ // is "NFC"
157
+ func normalize (str string , form ... norm.Form ) string {
158
+ f := norm .NFC
159
+ if len (form ) > 0 {
160
+ f = form [0 ]
161
+ }
162
+ t := transform .Chain (f , runes .Remove (runes .In (unicode .Mn )), f )
98
163
normStr , _ , _ := transform .String (t , str )
99
164
return normStr
100
165
}
@@ -103,13 +168,13 @@ func normalize(str string) string {
103
168
// with a single slash and normalizes unicode characters to "NFC". When using this method,
104
169
// `decode` should be an identity function so you don't decode strings twice.
105
170
func NormalizePathname (pathname string ) string {
171
+ pathname = decodeURI (pathname )
106
172
r := regexp2 .MustCompile ("\\ /+" , regexp2 .None )
107
- str , err := r .Replace (DecodeURIComponent (pathname , nil ),
108
- "/" , - 1 , - 1 )
173
+ pathname , err := r .Replace (pathname , "/" , - 1 , - 1 )
109
174
if err != nil {
110
175
panic (err )
111
176
}
112
- return normalize ( str )
177
+ return pathname
113
178
}
114
179
115
180
// Balanced bracket helper function.
@@ -146,7 +211,7 @@ func Parse(str string, o *Options) []interface{} {
146
211
if o == nil {
147
212
o = & Options {}
148
213
}
149
- defaultDelimiter := orString (o .Delimiter , defaultDelimiter )
214
+ defaultDelimiter := anyString (o .Delimiter , defaultDelimiter )
150
215
whitelist := o .Whitelist
151
216
152
217
// use list to deal with unicode in str
@@ -240,7 +305,7 @@ func Parse(str string, o *Options) []interface{} {
240
305
241
306
repeat := index < length && (arr [index ] == "+" || arr [index ] == "*" )
242
307
optional := index < length && (arr [index ] == "?" || arr [index ] == "*" )
243
- delimiter := orString (prefix , defaultDelimiter )
308
+ delimiter := anyString (prefix , defaultDelimiter )
244
309
245
310
// Increment `i` past modifier token.
246
311
if repeat || optional {
@@ -366,7 +431,7 @@ func tokensToFunction(tokens []interface{}, o *Options) (
366
431
o = & Options {}
367
432
}
368
433
reFlags := flags (o )
369
- encode , validate := EncodeURIComponent , true
434
+ encode , validate := encodeURIComponent , true
370
435
if o .Encode != nil {
371
436
encode = o .Encode
372
437
}
@@ -484,14 +549,8 @@ func tokensToFunction(tokens []interface{}, o *Options) (
484
549
}, nil
485
550
}
486
551
487
- func min (x , y int ) int {
488
- if x < y {
489
- return x
490
- }
491
- return y
492
- }
493
-
494
- func orString (str ... string ) string {
552
+ // Returns the first non empty string
553
+ func anyString (str ... string ) string {
495
554
for _ , v := range str {
496
555
if v != "" {
497
556
return v
@@ -500,26 +559,7 @@ func orString(str ...string) string {
500
559
return ""
501
560
}
502
561
503
- func indexOf (in interface {}, elem interface {}) int {
504
- inValue := reflect .ValueOf (in )
505
- elemValue := reflect .ValueOf (elem )
506
- inType := inValue .Type ()
507
-
508
- if inType .Kind () == reflect .String {
509
- return strings .Index (inValue .String (), elemValue .String ())
510
- }
511
-
512
- if inType .Kind () == reflect .Slice {
513
- for i := 0 ; i < inValue .Len (); i ++ {
514
- if reflect .DeepEqual (inValue .Index (i ).Interface (), elem ) {
515
- return i
516
- }
517
- }
518
- }
519
-
520
- return - 1
521
- }
522
-
562
+ // Returns the index of str in string slice
523
563
func stringIndexOf (arr []string , str string ) int {
524
564
for i , v := range arr {
525
565
if v == str {
@@ -529,6 +569,7 @@ func stringIndexOf(arr []string, str string) int {
529
569
return - 1
530
570
}
531
571
572
+ // Transform data which is reflect.Slice, reflect.Array to slice
532
573
func toSlice (data interface {}) []interface {} {
533
574
v := reflect .ValueOf (data )
534
575
length := v .Len ()
@@ -539,6 +580,7 @@ func toSlice(data interface{}) []interface{} {
539
580
return arr
540
581
}
541
582
583
+ // Transform data which is reflect.Map to map
542
584
func toMap (data interface {}) map [interface {}]interface {} {
543
585
v , m := reflect .ValueOf (data ), make (map [interface {}]interface {})
544
586
for _ , k := range v .MapKeys () {
@@ -548,32 +590,12 @@ func toMap(data interface{}) map[interface{}]interface{} {
548
590
return m
549
591
}
550
592
551
- func EncodeURI (str string ) string {
552
- excludes := ";/?:@&=+$,#"
553
- arr := strings .Split (str , "" )
554
- result := ""
555
- for _ , v := range arr {
556
- if strings .Contains (excludes , v ) {
557
- result += v
558
- } else {
559
- result += EncodeURIComponent (v , nil )
560
- }
561
- }
562
- return result
563
- }
564
-
565
- func EncodeURIComponent (str string , token interface {}) string {
566
- r := url .QueryEscape (str )
567
- r = strings .Replace (r , "+" , "%20" , - 1 )
568
- return r
593
+ func encodeURIComponent (str string , token interface {}) string {
594
+ return EncodeURIComponent (str )
569
595
}
570
596
571
- func DecodeURIComponent (str string , token interface {}) string {
572
- r , err := url .QueryUnescape (str )
573
- if err != nil {
574
- panic (err )
575
- }
576
- return r
597
+ func decodeURIComponent (str string , token interface {}) string {
598
+ return DecodeURIComponent (str )
577
599
}
578
600
579
601
// Escape a regular expression string.
@@ -687,7 +709,7 @@ func tokensToRegExp(rawTokens []interface{}, tokens *[]Token, o *Options) (*rege
687
709
}
688
710
}
689
711
690
- delimiter := orString (o .Delimiter , defaultDelimiter )
712
+ delimiter := anyString (o .Delimiter , defaultDelimiter )
691
713
arr := make ([]string , len (ends )+ 1 )
692
714
for i , v := range ends {
693
715
v = escapeString (v )
0 commit comments