3
3
4
4
use once_cell:: sync:: Lazy ;
5
5
use regex:: Regex ;
6
+ use regress;
6
7
use rustc_hash:: FxHashMap ;
7
8
8
9
const INTERCEPTION_ROUTE_MARKERS : [ & str ; 4 ] = [ "(..)(..)" , "(.)" , "(..)" , "(...)" ] ;
@@ -64,7 +65,7 @@ fn parse_parameter(param: &str) -> ParsedParameter {
64
65
}
65
66
66
67
fn escape_string_regexp ( segment : & str ) -> String {
67
- regex :: escape ( segment)
68
+ regress :: escape ( segment)
68
69
}
69
70
70
71
/// Removes the trailing slash for a given route or page path. Preserves the
@@ -164,6 +165,7 @@ fn get_safe_key_from_segment(
164
165
segment : & str ,
165
166
route_keys : & mut FxHashMap < String , String > ,
166
167
key_prefix : Option < & ' static str > ,
168
+ intercept_prefix : Option < & str > ,
167
169
) -> String {
168
170
let ParsedParameter {
169
171
key,
@@ -195,11 +197,13 @@ fn get_safe_key_from_segment(
195
197
} else {
196
198
route_keys. insert ( cleaned_key. clone ( ) , key) ;
197
199
}
200
+
201
+ let intercept_prefix = intercept_prefix. map_or_else ( String :: new, escape_string_regexp) ;
198
202
match ( repeat, optional) {
199
- ( true , true ) => format ! ( r"(?:/(?P<{cleaned_key}>.+?))?" ) ,
200
- ( true , false ) => format ! ( r"/(?P<{cleaned_key}>.+?)" ) ,
201
- ( false , true ) => format ! ( r"(?:/(?P<{cleaned_key}>[^/]+?))?" ) ,
202
- ( false , false ) => format ! ( r"/(?P<{cleaned_key}>[^/]+?)" ) ,
203
+ ( true , true ) => format ! ( r"(?:/{intercept_prefix} (?P<{cleaned_key}>.+?))?" ) ,
204
+ ( true , false ) => format ! ( r"/{intercept_prefix} (?P<{cleaned_key}>.+?)" ) ,
205
+ ( false , true ) => format ! ( r"(?:/{intercept_prefix} (?P<{cleaned_key}>[^/]+?))?" ) ,
206
+ ( false , false ) => format ! ( r"/{intercept_prefix} (?P<{cleaned_key}>[^/]+?)" ) ,
203
207
}
204
208
}
205
209
@@ -213,11 +217,12 @@ fn get_named_parametrized_route(
213
217
let parameterized_route = segments
214
218
. iter ( )
215
219
. map ( |segment| {
220
+ let interception_marker = INTERCEPTION_ROUTE_MARKERS
221
+ . iter ( )
222
+ . find ( |& m| segment. starts_with ( m) )
223
+ . copied ( ) ;
216
224
let key_prefix = if prefix_route_keys {
217
- let has_interception_marker = INTERCEPTION_ROUTE_MARKERS
218
- . iter ( )
219
- . any ( |& m| segment. starts_with ( m) ) ;
220
- if has_interception_marker {
225
+ if interception_marker. is_some ( ) {
221
226
Some ( NEXT_INTERCEPTION_MARKER_PREFIX )
222
227
} else {
223
228
Some ( NEXT_QUERY_PARAM_PREFIX )
@@ -233,6 +238,7 @@ fn get_named_parametrized_route(
233
238
& matches[ 1 ] ,
234
239
& mut route_keys,
235
240
key_prefix,
241
+ interception_marker,
236
242
) ;
237
243
}
238
244
format ! ( "/{}" , escape_string_regexp( segment) )
@@ -265,3 +271,39 @@ pub fn get_named_middleware_regex(normalized_route: &str) -> String {
265
271
let ( parameterized_route, _route_keys) = get_named_parametrized_route ( normalized_route, true ) ;
266
272
format ! ( "^{parameterized_route}(?:/)?$" )
267
273
}
274
+
275
+ #[ cfg( test) ]
276
+ mod test {
277
+ use super :: get_named_middleware_regex;
278
+
279
+ #[ test]
280
+ fn should_properly_handle_intercept_routes ( ) {
281
+ let tests = [
282
+ (
283
+ "/[locale]/example/(...)[locale]/intercepted" ,
284
+ "^/(?P<nxtPlocale>[^/]+?)/example/\\ (\\ .\\ .\\ .\\ )(?P<nxtIlocale>[^/]+?)/\
285
+ intercepted(?:/)?$",
286
+ ) ,
287
+ (
288
+ "/[locale]/example/(..)[locale]/intercepted" ,
289
+ "^/(?P<nxtPlocale>[^/]+?)/example/\\ (\\ .\\ .\\ )(?P<nxtIlocale>[^/]+?)/intercepted(?\
290
+ :/)?$",
291
+ ) ,
292
+ (
293
+ "/[locale]/example/(.)[locale]/intercepted" ,
294
+ "^/(?P<nxtPlocale>[^/]+?)/example/\\ (\\ .\\ )(?P<nxtIlocale>[^/]+?)/intercepted(?:/\
295
+ )?$",
296
+ ) ,
297
+ (
298
+ "/[locale]/example/(..)(..)[locale]/intercepted" ,
299
+ "^/(?P<nxtPlocale>[^/]+?)/example/\\ (\\ .\\ .\\ )\\ (\\ .\\ .\\ )(?P<nxtIlocale>[^/]+?)/\
300
+ intercepted(?:/)?$",
301
+ ) ,
302
+ ] ;
303
+
304
+ for test in tests {
305
+ let intercept_route = get_named_middleware_regex ( test. 0 ) ;
306
+ assert_eq ! ( intercept_route, test. 1 ) ;
307
+ }
308
+ }
309
+ }
0 commit comments