1
1
/**
2
2
* @coreapi
3
3
* @module url
4
- */ /** for typedoc */
4
+ */
5
+ /** for typedoc */
5
6
import {
6
- map , defaults , inherit , identity , unnest , tail , find , Obj , pairs , allTrueR , unnestR , arrayTuples
7
+ map , defaults , inherit , identity , unnest , tail , find , Obj , pairs , allTrueR , unnestR , arrayTuples
7
8
} from "../common/common" ;
8
- import { prop , propEq , pattern , eq , is , val } from "../common/hof" ;
9
+ import { prop , propEq } from "../common/hof" ;
9
10
import { isArray , isString , isDefined } from "../common/predicates" ;
10
11
import { Param , DefType } from "../params/param" ;
11
12
import { ParamTypes } from "../params/paramTypes" ;
@@ -35,11 +36,16 @@ function quoteRegExp(string: any, param?: any) {
35
36
const memoizeTo = ( obj : Obj , prop : string , fn : Function ) =>
36
37
obj [ prop ] = obj [ prop ] || fn ( ) ;
37
38
39
+ /** @hidden */
40
+ const splitOnSlash = splitOnDelim ( '/' ) ;
41
+
38
42
/** @hidden */
39
43
interface UrlMatcherCache {
40
- path : UrlMatcher [ ] ;
41
- parent : UrlMatcher ;
42
- pattern : RegExp ;
44
+ segments ?: any [ ] ;
45
+ weights ?: number [ ] ;
46
+ path ?: UrlMatcher [ ] ;
47
+ parent ?: UrlMatcher ;
48
+ pattern ?: RegExp ;
43
49
}
44
50
45
51
/**
@@ -98,7 +104,7 @@ export class UrlMatcher {
98
104
static nameValidator : RegExp = / ^ \w + ( [ - . ] + \w + ) * (?: \[ \] ) ? $ / ;
99
105
100
106
/** @hidden */
101
- private _cache : UrlMatcherCache = { path : [ this ] , parent : null , pattern : null } ;
107
+ private _cache : UrlMatcherCache = { path : [ this ] } ;
102
108
/** @hidden */
103
109
private _children : UrlMatcher [ ] = [ ] ;
104
110
/** @hidden */
@@ -474,8 +480,6 @@ export class UrlMatcher {
474
480
* The comparison function sorts static segments before dynamic ones.
475
481
*/
476
482
static compare ( a : UrlMatcher , b : UrlMatcher ) : number {
477
- const splitOnSlash = splitOnDelim ( '/' ) ;
478
-
479
483
/**
480
484
* Turn a UrlMatcher and all its parent matchers into an array
481
485
* of slash literals '/', string literals, and Param objects
@@ -484,27 +488,38 @@ export class UrlMatcher {
484
488
* var matcher = $umf.compile("/foo").append($umf.compile("/:param")).append($umf.compile("/")).append($umf.compile("tail"));
485
489
* var result = segments(matcher); // [ '/', 'foo', '/', Param, '/', 'tail' ]
486
490
*
491
+ * Caches the result as `matcher._cache.segments`
487
492
*/
488
493
const segments = ( matcher : UrlMatcher ) =>
489
- matcher . _cache . path . map ( UrlMatcher . pathSegmentsAndParams )
490
- . reduce ( unnestR , [ ] )
491
- . reduce ( joinNeighborsR , [ ] )
492
- . map ( x => isString ( x ) ? splitOnSlash ( x ) : x )
493
- . reduce ( unnestR , [ ] ) ;
494
-
495
- let aSegments = segments ( a ) , bSegments = segments ( b ) ;
496
- // console.table( { aSegments, bSegments });
497
-
498
- // Sort slashes first, then static strings, the Params
499
- const weight = pattern ( [
500
- [ eq ( "/" ) , val ( 1 ) ] ,
501
- [ isString , val ( 2 ) ] ,
502
- [ is ( Param ) , val ( 3 ) ]
503
- ] ) ;
504
- let pairs = arrayTuples ( aSegments . map ( weight ) , bSegments . map ( weight ) ) ;
505
- // console.table(pairs);
506
-
507
- return pairs . reduce ( ( cmp , weightPair ) => cmp !== 0 ? cmp : weightPair [ 0 ] - weightPair [ 1 ] , 0 ) ;
494
+ matcher . _cache . segments = matcher . _cache . segments ||
495
+ matcher . _cache . path . map ( UrlMatcher . pathSegmentsAndParams )
496
+ . reduce ( unnestR , [ ] )
497
+ . reduce ( joinNeighborsR , [ ] )
498
+ . map ( x => isString ( x ) ? splitOnSlash ( x ) : x )
499
+ . reduce ( unnestR , [ ] ) ;
500
+
501
+ /**
502
+ * Gets the sort weight for each segment of a UrlMatcher
503
+ *
504
+ * Caches the result as `matcher._cache.weights`
505
+ */
506
+ const weights = ( matcher : UrlMatcher ) =>
507
+ matcher . _cache . weights = matcher . _cache . weights ||
508
+ segments ( matcher ) . map ( segment => {
509
+ // Sort slashes first, then static strings, the Params
510
+ if ( segment === '/' ) return 1 ;
511
+ if ( isString ( segment ) ) return 2 ;
512
+ if ( segment instanceof Param ) return 3 ;
513
+ } ) ;
514
+
515
+ let cmp , i , pairs = arrayTuples ( weights ( a ) , weights ( b ) ) ;
516
+
517
+ for ( i = 0 ; i < pairs . length ; i ++ ) {
518
+ cmp = pairs [ i ] [ 0 ] - pairs [ i ] [ 1 ] ;
519
+ if ( cmp !== 0 ) return cmp ;
520
+ }
521
+
522
+ return 0 ;
508
523
}
509
524
}
510
525
0 commit comments