@devp0nt/route0 1.0.0-next.80 → 1.0.0-next.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +210 -173
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +66 -86
- package/dist/esm/index.d.ts +66 -86
- package/dist/esm/index.js +210 -173
- package/dist/esm/index.js.map +1 -1
- package/package.json +8 -2
package/dist/esm/index.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { parse as parseSearchQuery, stringify as stringifySearchQuery } from "@devp0nt/flat0";
|
|
2
2
|
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3
3
|
const collapseDuplicateSlashes = (value) => value.replace(/\/{2,}/g, "/");
|
|
4
|
-
const normalizeSlashPath = (value) => {
|
|
5
|
-
const collapsed = collapseDuplicateSlashes(value);
|
|
6
|
-
if (collapsed === "" || collapsed === "/") return "/";
|
|
7
|
-
const withLeadingSlash = collapsed.startsWith("/") ? collapsed : `/${collapsed}`;
|
|
8
|
-
return withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
9
|
-
};
|
|
10
4
|
class Route0 {
|
|
11
5
|
definition;
|
|
12
6
|
params;
|
|
@@ -26,16 +20,16 @@ class Route0 {
|
|
|
26
20
|
_captureKeys;
|
|
27
21
|
_normalizedDefinition;
|
|
28
22
|
_definitionParts;
|
|
23
|
+
static normalizeSlash = (value) => {
|
|
24
|
+
const collapsed = collapseDuplicateSlashes(value);
|
|
25
|
+
if (collapsed === "" || collapsed === "/") return "/";
|
|
26
|
+
const withLeadingSlash = collapsed.startsWith("/") ? collapsed : `/${collapsed}`;
|
|
27
|
+
return withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
28
|
+
};
|
|
29
29
|
static _getRouteSegments(definition) {
|
|
30
30
|
if (definition === "" || definition === "/") return [];
|
|
31
31
|
return definition.split("/").filter(Boolean);
|
|
32
32
|
}
|
|
33
|
-
static _normalizeRouteDefinition(definition) {
|
|
34
|
-
return normalizeSlashPath(definition);
|
|
35
|
-
}
|
|
36
|
-
static _normalizePathname(pathname) {
|
|
37
|
-
return Route0._normalizeRouteDefinition(pathname);
|
|
38
|
-
}
|
|
39
33
|
static _validateRouteDefinition(definition) {
|
|
40
34
|
const segments = Route0._getRouteSegments(definition);
|
|
41
35
|
const wildcardSegments = segments.filter((segment) => segment.includes("*"));
|
|
@@ -66,7 +60,7 @@ class Route0 {
|
|
|
66
60
|
this._origin = origin;
|
|
67
61
|
}
|
|
68
62
|
constructor(definition, config = {}) {
|
|
69
|
-
const normalizedDefinition = Route0.
|
|
63
|
+
const normalizedDefinition = Route0.normalizeSlash(definition);
|
|
70
64
|
Route0._validateRouteDefinition(normalizedDefinition);
|
|
71
65
|
this.definition = normalizedDefinition;
|
|
72
66
|
this.params = this.pathParamsDefinition;
|
|
@@ -98,7 +92,7 @@ class Route0 {
|
|
|
98
92
|
return definition.clone(config);
|
|
99
93
|
}
|
|
100
94
|
const original = new Route0(
|
|
101
|
-
Route0.
|
|
95
|
+
Route0.normalizeSlash(definition),
|
|
102
96
|
config
|
|
103
97
|
);
|
|
104
98
|
return original._callable;
|
|
@@ -113,7 +107,7 @@ class Route0 {
|
|
|
113
107
|
return definition;
|
|
114
108
|
}
|
|
115
109
|
const original = typeof definition === "object" ? definition : new Route0(
|
|
116
|
-
Route0.
|
|
110
|
+
Route0.normalizeSlash(definition)
|
|
117
111
|
);
|
|
118
112
|
return original._callable;
|
|
119
113
|
}
|
|
@@ -125,7 +119,7 @@ class Route0 {
|
|
|
125
119
|
}
|
|
126
120
|
/** Extends the current route definition by appending a suffix route. */
|
|
127
121
|
extend(suffixDefinition) {
|
|
128
|
-
const definition = Route0.
|
|
122
|
+
const definition = Route0.normalizeSlash(`${this.definitionWithoutTrailingWildcard}/${suffixDefinition}`);
|
|
129
123
|
return Route0.create(
|
|
130
124
|
definition,
|
|
131
125
|
{
|
|
@@ -200,7 +194,7 @@ class Route0 {
|
|
|
200
194
|
});
|
|
201
195
|
url = url.replace(/\*\?/g, () => String(paramsInput["*"] ?? ""));
|
|
202
196
|
url = url.replace(/\*/g, () => String(paramsInput["*"] ?? ""));
|
|
203
|
-
const searchString = stringifySearchQuery(searchInput);
|
|
197
|
+
const searchString = stringifySearchQuery(searchInput, { arrayIndexes: false });
|
|
204
198
|
url = [url, searchString].filter(Boolean).join("?");
|
|
205
199
|
url = collapseDuplicateSlashes(url);
|
|
206
200
|
url = absInput ? Route0._getAbsPath(absOriginInput || this.origin, url) : url;
|
|
@@ -382,15 +376,34 @@ class Route0 {
|
|
|
382
376
|
}
|
|
383
377
|
return this._definitionParts;
|
|
384
378
|
}
|
|
385
|
-
/** Fast pathname exact match check without building a full
|
|
386
|
-
|
|
387
|
-
|
|
379
|
+
/** Fast pathname exact match check without building a full relation object. */
|
|
380
|
+
isExact(pathname, normalize = true) {
|
|
381
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
382
|
+
return this.regex.test(normalizedPathname);
|
|
388
383
|
}
|
|
389
|
-
/** Fast pathname exact or ancestor match check without building a full
|
|
390
|
-
|
|
391
|
-
const normalizedPathname = Route0.
|
|
384
|
+
/** Fast pathname exact or ancestor match check without building a full relation object. */
|
|
385
|
+
isExactOrAncestor(pathname, normalize = true) {
|
|
386
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
392
387
|
return this.regex.test(normalizedPathname) || this.regexAncestor.test(normalizedPathname);
|
|
393
388
|
}
|
|
389
|
+
/** True when route is ancestor of pathname (pathname is deeper). */
|
|
390
|
+
isAncestor(pathname, normalize = true) {
|
|
391
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
392
|
+
return !this.regex.test(normalizedPathname) && this.regexAncestor.test(normalizedPathname);
|
|
393
|
+
}
|
|
394
|
+
/** True when route is descendant of pathname (pathname is shallower). */
|
|
395
|
+
isDescendant(pathname, normalize = true) {
|
|
396
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
397
|
+
if (this.regex.test(normalizedPathname) || this.regexAncestor.test(normalizedPathname)) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
for (const matcher of this.regexDescendantMatchers) {
|
|
401
|
+
if (normalizedPathname.match(matcher.regex)) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
394
407
|
/** Creates a grouped regex pattern string from many routes. */
|
|
395
408
|
static getRegexStringGroup(routes) {
|
|
396
409
|
const patterns = routes.map((route) => route.regexString).join("|");
|
|
@@ -437,11 +450,16 @@ class Route0 {
|
|
|
437
450
|
const abs = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(hrefOrHrefRelOrLocation);
|
|
438
451
|
const base = abs ? void 0 : "http://example.com";
|
|
439
452
|
const url = new URL(hrefOrHrefRelOrLocation, base);
|
|
440
|
-
const search = parseSearchQuery(url.search);
|
|
441
453
|
const hrefRel = url.pathname + url.search + url.hash;
|
|
454
|
+
let _search;
|
|
442
455
|
const location = {
|
|
443
456
|
pathname: url.pathname,
|
|
444
|
-
search
|
|
457
|
+
get search() {
|
|
458
|
+
if (_search === void 0) {
|
|
459
|
+
_search = parseSearchQuery(url.search);
|
|
460
|
+
}
|
|
461
|
+
return _search;
|
|
462
|
+
},
|
|
445
463
|
searchString: url.search,
|
|
446
464
|
hash: url.hash,
|
|
447
465
|
origin: abs ? url.origin : void 0,
|
|
@@ -454,73 +472,91 @@ class Route0 {
|
|
|
454
472
|
port: abs ? url.port || void 0 : void 0,
|
|
455
473
|
// specific to UnknownLocation
|
|
456
474
|
params: void 0,
|
|
457
|
-
route: void 0
|
|
458
|
-
known: false,
|
|
459
|
-
exact: false,
|
|
460
|
-
ancestor: false,
|
|
461
|
-
descendant: false,
|
|
462
|
-
unmatched: false
|
|
475
|
+
route: void 0
|
|
463
476
|
};
|
|
464
477
|
return location;
|
|
465
478
|
}
|
|
466
|
-
|
|
479
|
+
getRelation(hrefOrHrefRelOrLocation) {
|
|
467
480
|
if (hrefOrHrefRelOrLocation instanceof URL) {
|
|
468
|
-
return this.
|
|
481
|
+
return this.getRelation(hrefOrHrefRelOrLocation.href);
|
|
469
482
|
}
|
|
470
483
|
if (typeof hrefOrHrefRelOrLocation !== "string") {
|
|
471
484
|
hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel;
|
|
472
485
|
}
|
|
473
|
-
const
|
|
474
|
-
location.route = this.definition;
|
|
475
|
-
location.params = {};
|
|
476
|
-
const pathname = Route0._normalizePathname(location.pathname);
|
|
486
|
+
const pathname = Route0.normalizeSlash(new URL(hrefOrHrefRelOrLocation, "http://example.com").pathname);
|
|
477
487
|
const paramNames = this.captureKeys;
|
|
478
488
|
const exactRe = this.regex;
|
|
479
|
-
const ancestorRe = this.regexAncestor;
|
|
480
489
|
const exactMatch = pathname.match(exactRe);
|
|
490
|
+
if (exactMatch) {
|
|
491
|
+
const values = exactMatch.slice(1, 1 + paramNames.length);
|
|
492
|
+
const params = Object.fromEntries(
|
|
493
|
+
paramNames.map((n, i) => {
|
|
494
|
+
const value = values[i];
|
|
495
|
+
return [n, value === void 0 ? void 0 : decodeURIComponent(value)];
|
|
496
|
+
})
|
|
497
|
+
);
|
|
498
|
+
return {
|
|
499
|
+
type: "exact",
|
|
500
|
+
route: this.definition,
|
|
501
|
+
params,
|
|
502
|
+
exact: true,
|
|
503
|
+
ancestor: false,
|
|
504
|
+
descendant: false,
|
|
505
|
+
unmatched: false
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
const ancestorRe = this.regexAncestor;
|
|
481
509
|
const ancestorMatch = pathname.match(ancestorRe);
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const paramsMatch = exactMatch || (ancestor ? ancestorMatch : null);
|
|
485
|
-
if (paramsMatch) {
|
|
486
|
-
const values = paramsMatch.slice(1, 1 + paramNames.length);
|
|
510
|
+
if (ancestorMatch) {
|
|
511
|
+
const values = ancestorMatch.slice(1, 1 + paramNames.length);
|
|
487
512
|
const params = Object.fromEntries(
|
|
488
513
|
paramNames.map((n, i) => {
|
|
489
514
|
const value = values[i];
|
|
490
515
|
return [n, value === void 0 ? void 0 : decodeURIComponent(value)];
|
|
491
516
|
})
|
|
492
517
|
);
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
518
|
+
return {
|
|
519
|
+
type: "ancestor",
|
|
520
|
+
route: this.definition,
|
|
521
|
+
params,
|
|
522
|
+
exact: false,
|
|
523
|
+
ancestor: true,
|
|
524
|
+
descendant: false,
|
|
525
|
+
unmatched: false
|
|
526
|
+
};
|
|
496
527
|
}
|
|
497
|
-
let descendant = false;
|
|
498
528
|
let descendantMatch = null;
|
|
499
529
|
let descendantCaptureKeys = [];
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
const unmatched = !exact && !ancestor && !descendant;
|
|
511
|
-
if (descendant && descendantMatch) {
|
|
530
|
+
for (const matcher of this.regexDescendantMatchers) {
|
|
531
|
+
const match = pathname.match(matcher.regex);
|
|
532
|
+
if (!match) continue;
|
|
533
|
+
descendantMatch = match;
|
|
534
|
+
descendantCaptureKeys = matcher.captureKeys;
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
if (descendantMatch) {
|
|
512
538
|
const values = descendantMatch.slice(1, 1 + descendantCaptureKeys.length);
|
|
513
|
-
|
|
539
|
+
const params = Object.fromEntries(
|
|
514
540
|
descendantCaptureKeys.map((key, index) => [key, decodeURIComponent(values[index])])
|
|
515
541
|
);
|
|
542
|
+
return {
|
|
543
|
+
type: "descendant",
|
|
544
|
+
route: this.definition,
|
|
545
|
+
params,
|
|
546
|
+
exact: false,
|
|
547
|
+
ancestor: false,
|
|
548
|
+
descendant: true,
|
|
549
|
+
unmatched: false
|
|
550
|
+
};
|
|
516
551
|
}
|
|
517
552
|
return {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
553
|
+
type: "unmatched",
|
|
554
|
+
route: this.definition,
|
|
555
|
+
params: {},
|
|
556
|
+
exact: false,
|
|
557
|
+
ancestor: false,
|
|
558
|
+
descendant: false,
|
|
559
|
+
unmatched: true
|
|
524
560
|
};
|
|
525
561
|
}
|
|
526
562
|
_validateParamsInput(input) {
|
|
@@ -609,90 +645,106 @@ class Route0 {
|
|
|
609
645
|
parse: (value) => this._parseSchemaResult(this._validateParamsInput(value)),
|
|
610
646
|
safeParse: (value) => this._safeParseSchemaResult(this._validateParamsInput(value))
|
|
611
647
|
};
|
|
612
|
-
/** True when path structure is equal (param names are ignored). */
|
|
613
|
-
isSame(other) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
648
|
+
// /** True when path structure is equal (param names are ignored). */
|
|
649
|
+
// isSame(other: AnyRoute): boolean {
|
|
650
|
+
// const thisShape = this.routeTokens
|
|
651
|
+
// .map((t) => {
|
|
652
|
+
// if (t.kind === 'static') return `s:${t.value}`
|
|
653
|
+
// if (t.kind === 'param') return `p:${t.optional ? 'o' : 'r'}`
|
|
654
|
+
// return `w:${t.prefix}:${t.optional ? 'o' : 'r'}`
|
|
655
|
+
// })
|
|
656
|
+
// .join('/')
|
|
657
|
+
// const otherRoute = Route0.from(other) as Route0<string, UnknownSearchInput>
|
|
658
|
+
// const otherShape = otherRoute.routeTokens
|
|
659
|
+
// .map((t) => {
|
|
660
|
+
// if (t.kind === 'static') return `s:${t.value}`
|
|
661
|
+
// if (t.kind === 'param') return `p:${t.optional ? 'o' : 'r'}`
|
|
662
|
+
// return `w:${t.prefix}:${t.optional ? 'o' : 'r'}`
|
|
663
|
+
// })
|
|
664
|
+
// .join('/')
|
|
665
|
+
// return thisShape === otherShape
|
|
666
|
+
// }
|
|
667
|
+
// /** Static convenience wrapper for `isSame`. */
|
|
668
|
+
// static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean {
|
|
669
|
+
// if (!a) {
|
|
670
|
+
// if (!b) return true
|
|
671
|
+
// return false
|
|
672
|
+
// }
|
|
673
|
+
// if (!b) {
|
|
674
|
+
// return false
|
|
675
|
+
// }
|
|
676
|
+
// return Route0.create(a).isSame(Route0.create(b))
|
|
677
|
+
// }
|
|
678
|
+
// /** True when current route is more specific/deeper than `other`. */
|
|
679
|
+
// isDescendant(other: AnyRoute | string | undefined): boolean {
|
|
680
|
+
// if (!other) return false
|
|
681
|
+
// other = Route0.create(other)
|
|
682
|
+
// // this is a descendant of other if:
|
|
683
|
+
// // - paths are not exactly the same
|
|
684
|
+
// // - other's path is a prefix of this path, matching params as wildcards
|
|
685
|
+
// const getParts = (path: string) => (path === '/' ? ['/'] : path.split('/').filter(Boolean))
|
|
686
|
+
// // Root is ancestor of any non-root; thus any non-root is a descendant of root
|
|
687
|
+
// if (other.definition === '/' && this.definition !== '/') {
|
|
688
|
+
// return true
|
|
689
|
+
// }
|
|
690
|
+
// const thisParts = getParts(this.definition)
|
|
691
|
+
// const otherParts = getParts(other.definition)
|
|
692
|
+
// // A descendant must be deeper
|
|
693
|
+
// if (thisParts.length <= otherParts.length) return false
|
|
694
|
+
// const matchesPatternPart = (patternPart: string, valuePart: string): { match: boolean; wildcard: boolean } => {
|
|
695
|
+
// if (patternPart.startsWith(':')) return { match: true, wildcard: false }
|
|
696
|
+
// const wildcardIndex = patternPart.indexOf('*')
|
|
697
|
+
// if (wildcardIndex >= 0) {
|
|
698
|
+
// const prefix = patternPart.slice(0, wildcardIndex)
|
|
699
|
+
// return { match: prefix.length === 0 || valuePart.startsWith(prefix), wildcard: true }
|
|
700
|
+
// }
|
|
701
|
+
// return { match: patternPart === valuePart, wildcard: false }
|
|
702
|
+
// }
|
|
703
|
+
// for (let i = 0; i < otherParts.length; i++) {
|
|
704
|
+
// const otherPart = otherParts[i]
|
|
705
|
+
// const thisPart = thisParts[i]
|
|
706
|
+
// const result = matchesPatternPart(otherPart, thisPart)
|
|
707
|
+
// if (!result.match) return false
|
|
708
|
+
// if (result.wildcard) return true
|
|
709
|
+
// }
|
|
710
|
+
// // Not equal (depth already ensures not equal)
|
|
711
|
+
// return true
|
|
712
|
+
// }
|
|
713
|
+
// /** True when current route is broader/shallower than `other`. */
|
|
714
|
+
// isAncestor(other: AnyRoute | string | undefined): boolean {
|
|
715
|
+
// if (!other) return false
|
|
716
|
+
// other = Route0.create(other)
|
|
717
|
+
// // this is an ancestor of other if:
|
|
718
|
+
// // - paths are not exactly the same
|
|
719
|
+
// // - this path is a prefix of other path, matching params as wildcards
|
|
720
|
+
// const getParts = (path: string) => (path === '/' ? ['/'] : path.split('/').filter(Boolean))
|
|
721
|
+
// // Root is ancestor of any non-root path
|
|
722
|
+
// if (this.definition === '/' && other.definition !== '/') {
|
|
723
|
+
// return true
|
|
724
|
+
// }
|
|
725
|
+
// const thisParts = getParts(this.definition)
|
|
726
|
+
// const otherParts = getParts(other.definition)
|
|
727
|
+
// // An ancestor must be shallower
|
|
728
|
+
// if (thisParts.length >= otherParts.length) return false
|
|
729
|
+
// const matchesPatternPart = (patternPart: string, valuePart: string): { match: boolean; wildcard: boolean } => {
|
|
730
|
+
// if (patternPart.startsWith(':')) return { match: true, wildcard: false }
|
|
731
|
+
// const wildcardIndex = patternPart.indexOf('*')
|
|
732
|
+
// if (wildcardIndex >= 0) {
|
|
733
|
+
// const prefix = patternPart.slice(0, wildcardIndex)
|
|
734
|
+
// return { match: prefix.length === 0 || valuePart.startsWith(prefix), wildcard: true }
|
|
735
|
+
// }
|
|
736
|
+
// return { match: patternPart === valuePart, wildcard: false }
|
|
737
|
+
// }
|
|
738
|
+
// for (let i = 0; i < thisParts.length; i++) {
|
|
739
|
+
// const thisPart = thisParts[i]
|
|
740
|
+
// const otherPart = otherParts[i]
|
|
741
|
+
// const result = matchesPatternPart(thisPart, otherPart)
|
|
742
|
+
// if (!result.match) return false
|
|
743
|
+
// if (result.wildcard) return true
|
|
744
|
+
// }
|
|
745
|
+
// // Not equal (depth already ensures not equal)
|
|
746
|
+
// return true
|
|
747
|
+
// }
|
|
696
748
|
/** True when two route patterns can match the same concrete URL. */
|
|
697
749
|
isOverlap(other) {
|
|
698
750
|
if (!other) return false;
|
|
@@ -750,21 +802,6 @@ class Route0 {
|
|
|
750
802
|
}
|
|
751
803
|
}
|
|
752
804
|
class Routes {
|
|
753
|
-
static _getNormalizedPathnameFromInput(hrefOrHrefRelOrLocation) {
|
|
754
|
-
if (hrefOrHrefRelOrLocation instanceof URL) {
|
|
755
|
-
return normalizeSlashPath(hrefOrHrefRelOrLocation.pathname);
|
|
756
|
-
}
|
|
757
|
-
if (typeof hrefOrHrefRelOrLocation !== "string") {
|
|
758
|
-
if (typeof hrefOrHrefRelOrLocation.pathname === "string") {
|
|
759
|
-
return normalizeSlashPath(hrefOrHrefRelOrLocation.pathname);
|
|
760
|
-
}
|
|
761
|
-
hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel;
|
|
762
|
-
}
|
|
763
|
-
const abs = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(hrefOrHrefRelOrLocation);
|
|
764
|
-
const base = abs ? void 0 : "http://example.com";
|
|
765
|
-
const url = new URL(hrefOrHrefRelOrLocation, base);
|
|
766
|
-
return normalizeSlashPath(url.pathname);
|
|
767
|
-
}
|
|
768
805
|
_routes;
|
|
769
806
|
_pathsOrdering;
|
|
770
807
|
_keysOrdering;
|
|
@@ -828,17 +865,17 @@ class Routes {
|
|
|
828
865
|
}
|
|
829
866
|
_getLocation(hrefOrHrefRelOrLocation) {
|
|
830
867
|
const input = hrefOrHrefRelOrLocation;
|
|
831
|
-
const
|
|
868
|
+
const location = Route0.getLocation(input);
|
|
832
869
|
for (const route of this._ordered) {
|
|
833
|
-
if (
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
870
|
+
if (route.isExact(location.pathname, false)) {
|
|
871
|
+
const relation = route.getRelation(input);
|
|
872
|
+
return Object.assign(location, {
|
|
873
|
+
route: route.definition,
|
|
874
|
+
params: relation.params
|
|
875
|
+
});
|
|
839
876
|
}
|
|
840
877
|
}
|
|
841
|
-
return
|
|
878
|
+
return location;
|
|
842
879
|
}
|
|
843
880
|
static makeOrdering(routes) {
|
|
844
881
|
const hydrated = Routes.hydrate(routes);
|