@devp0nt/route0 1.0.0-next.80 → 1.0.0-next.81
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 +64 -84
- package/dist/esm/index.d.ts +64 -84
- package/dist/esm/index.js +210 -173
- package/dist/esm/index.js.map +1 -1
- package/package.json +8 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -25,12 +25,6 @@ module.exports = __toCommonJS(index_exports);
|
|
|
25
25
|
var import_flat0 = require("@devp0nt/flat0");
|
|
26
26
|
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27
27
|
const collapseDuplicateSlashes = (value) => value.replace(/\/{2,}/g, "/");
|
|
28
|
-
const normalizeSlashPath = (value) => {
|
|
29
|
-
const collapsed = collapseDuplicateSlashes(value);
|
|
30
|
-
if (collapsed === "" || collapsed === "/") return "/";
|
|
31
|
-
const withLeadingSlash = collapsed.startsWith("/") ? collapsed : `/${collapsed}`;
|
|
32
|
-
return withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
33
|
-
};
|
|
34
28
|
class Route0 {
|
|
35
29
|
definition;
|
|
36
30
|
params;
|
|
@@ -50,16 +44,16 @@ class Route0 {
|
|
|
50
44
|
_captureKeys;
|
|
51
45
|
_normalizedDefinition;
|
|
52
46
|
_definitionParts;
|
|
47
|
+
static normalizeSlash = (value) => {
|
|
48
|
+
const collapsed = collapseDuplicateSlashes(value);
|
|
49
|
+
if (collapsed === "" || collapsed === "/") return "/";
|
|
50
|
+
const withLeadingSlash = collapsed.startsWith("/") ? collapsed : `/${collapsed}`;
|
|
51
|
+
return withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
52
|
+
};
|
|
53
53
|
static _getRouteSegments(definition) {
|
|
54
54
|
if (definition === "" || definition === "/") return [];
|
|
55
55
|
return definition.split("/").filter(Boolean);
|
|
56
56
|
}
|
|
57
|
-
static _normalizeRouteDefinition(definition) {
|
|
58
|
-
return normalizeSlashPath(definition);
|
|
59
|
-
}
|
|
60
|
-
static _normalizePathname(pathname) {
|
|
61
|
-
return Route0._normalizeRouteDefinition(pathname);
|
|
62
|
-
}
|
|
63
57
|
static _validateRouteDefinition(definition) {
|
|
64
58
|
const segments = Route0._getRouteSegments(definition);
|
|
65
59
|
const wildcardSegments = segments.filter((segment) => segment.includes("*"));
|
|
@@ -90,7 +84,7 @@ class Route0 {
|
|
|
90
84
|
this._origin = origin;
|
|
91
85
|
}
|
|
92
86
|
constructor(definition, config = {}) {
|
|
93
|
-
const normalizedDefinition = Route0.
|
|
87
|
+
const normalizedDefinition = Route0.normalizeSlash(definition);
|
|
94
88
|
Route0._validateRouteDefinition(normalizedDefinition);
|
|
95
89
|
this.definition = normalizedDefinition;
|
|
96
90
|
this.params = this.pathParamsDefinition;
|
|
@@ -122,7 +116,7 @@ class Route0 {
|
|
|
122
116
|
return definition.clone(config);
|
|
123
117
|
}
|
|
124
118
|
const original = new Route0(
|
|
125
|
-
Route0.
|
|
119
|
+
Route0.normalizeSlash(definition),
|
|
126
120
|
config
|
|
127
121
|
);
|
|
128
122
|
return original._callable;
|
|
@@ -137,7 +131,7 @@ class Route0 {
|
|
|
137
131
|
return definition;
|
|
138
132
|
}
|
|
139
133
|
const original = typeof definition === "object" ? definition : new Route0(
|
|
140
|
-
Route0.
|
|
134
|
+
Route0.normalizeSlash(definition)
|
|
141
135
|
);
|
|
142
136
|
return original._callable;
|
|
143
137
|
}
|
|
@@ -149,7 +143,7 @@ class Route0 {
|
|
|
149
143
|
}
|
|
150
144
|
/** Extends the current route definition by appending a suffix route. */
|
|
151
145
|
extend(suffixDefinition) {
|
|
152
|
-
const definition = Route0.
|
|
146
|
+
const definition = Route0.normalizeSlash(`${this.definitionWithoutTrailingWildcard}/${suffixDefinition}`);
|
|
153
147
|
return Route0.create(
|
|
154
148
|
definition,
|
|
155
149
|
{
|
|
@@ -224,7 +218,7 @@ class Route0 {
|
|
|
224
218
|
});
|
|
225
219
|
url = url.replace(/\*\?/g, () => String(paramsInput["*"] ?? ""));
|
|
226
220
|
url = url.replace(/\*/g, () => String(paramsInput["*"] ?? ""));
|
|
227
|
-
const searchString = (0, import_flat0.stringify)(searchInput);
|
|
221
|
+
const searchString = (0, import_flat0.stringify)(searchInput, { arrayIndexes: false });
|
|
228
222
|
url = [url, searchString].filter(Boolean).join("?");
|
|
229
223
|
url = collapseDuplicateSlashes(url);
|
|
230
224
|
url = absInput ? Route0._getAbsPath(absOriginInput || this.origin, url) : url;
|
|
@@ -406,15 +400,34 @@ class Route0 {
|
|
|
406
400
|
}
|
|
407
401
|
return this._definitionParts;
|
|
408
402
|
}
|
|
409
|
-
/** Fast pathname exact match check without building a full
|
|
410
|
-
|
|
411
|
-
|
|
403
|
+
/** Fast pathname exact match check without building a full relation object. */
|
|
404
|
+
isExact(pathname, normalize = true) {
|
|
405
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
406
|
+
return this.regex.test(normalizedPathname);
|
|
412
407
|
}
|
|
413
|
-
/** Fast pathname exact or ancestor match check without building a full
|
|
414
|
-
|
|
415
|
-
const normalizedPathname = Route0.
|
|
408
|
+
/** Fast pathname exact or ancestor match check without building a full relation object. */
|
|
409
|
+
isExactOrAncestor(pathname, normalize = true) {
|
|
410
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
416
411
|
return this.regex.test(normalizedPathname) || this.regexAncestor.test(normalizedPathname);
|
|
417
412
|
}
|
|
413
|
+
/** True when route is ancestor of pathname (pathname is deeper). */
|
|
414
|
+
isAncestor(pathname, normalize = true) {
|
|
415
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
416
|
+
return !this.regex.test(normalizedPathname) && this.regexAncestor.test(normalizedPathname);
|
|
417
|
+
}
|
|
418
|
+
/** True when route is descendant of pathname (pathname is shallower). */
|
|
419
|
+
isDescendant(pathname, normalize = true) {
|
|
420
|
+
const normalizedPathname = normalize ? Route0.normalizeSlash(pathname) : pathname;
|
|
421
|
+
if (this.regex.test(normalizedPathname) || this.regexAncestor.test(normalizedPathname)) {
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
for (const matcher of this.regexDescendantMatchers) {
|
|
425
|
+
if (normalizedPathname.match(matcher.regex)) {
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
418
431
|
/** Creates a grouped regex pattern string from many routes. */
|
|
419
432
|
static getRegexStringGroup(routes) {
|
|
420
433
|
const patterns = routes.map((route) => route.regexString).join("|");
|
|
@@ -461,11 +474,16 @@ class Route0 {
|
|
|
461
474
|
const abs = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(hrefOrHrefRelOrLocation);
|
|
462
475
|
const base = abs ? void 0 : "http://example.com";
|
|
463
476
|
const url = new URL(hrefOrHrefRelOrLocation, base);
|
|
464
|
-
const search = (0, import_flat0.parse)(url.search);
|
|
465
477
|
const hrefRel = url.pathname + url.search + url.hash;
|
|
478
|
+
let _search;
|
|
466
479
|
const location = {
|
|
467
480
|
pathname: url.pathname,
|
|
468
|
-
search
|
|
481
|
+
get search() {
|
|
482
|
+
if (_search === void 0) {
|
|
483
|
+
_search = (0, import_flat0.parse)(url.search);
|
|
484
|
+
}
|
|
485
|
+
return _search;
|
|
486
|
+
},
|
|
469
487
|
searchString: url.search,
|
|
470
488
|
hash: url.hash,
|
|
471
489
|
origin: abs ? url.origin : void 0,
|
|
@@ -478,73 +496,91 @@ class Route0 {
|
|
|
478
496
|
port: abs ? url.port || void 0 : void 0,
|
|
479
497
|
// specific to UnknownLocation
|
|
480
498
|
params: void 0,
|
|
481
|
-
route: void 0
|
|
482
|
-
known: false,
|
|
483
|
-
exact: false,
|
|
484
|
-
ancestor: false,
|
|
485
|
-
descendant: false,
|
|
486
|
-
unmatched: false
|
|
499
|
+
route: void 0
|
|
487
500
|
};
|
|
488
501
|
return location;
|
|
489
502
|
}
|
|
490
|
-
|
|
503
|
+
getRelation(hrefOrHrefRelOrLocation) {
|
|
491
504
|
if (hrefOrHrefRelOrLocation instanceof URL) {
|
|
492
|
-
return this.
|
|
505
|
+
return this.getRelation(hrefOrHrefRelOrLocation.href);
|
|
493
506
|
}
|
|
494
507
|
if (typeof hrefOrHrefRelOrLocation !== "string") {
|
|
495
508
|
hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel;
|
|
496
509
|
}
|
|
497
|
-
const
|
|
498
|
-
location.route = this.definition;
|
|
499
|
-
location.params = {};
|
|
500
|
-
const pathname = Route0._normalizePathname(location.pathname);
|
|
510
|
+
const pathname = Route0.normalizeSlash(new URL(hrefOrHrefRelOrLocation, "http://example.com").pathname);
|
|
501
511
|
const paramNames = this.captureKeys;
|
|
502
512
|
const exactRe = this.regex;
|
|
503
|
-
const ancestorRe = this.regexAncestor;
|
|
504
513
|
const exactMatch = pathname.match(exactRe);
|
|
514
|
+
if (exactMatch) {
|
|
515
|
+
const values = exactMatch.slice(1, 1 + paramNames.length);
|
|
516
|
+
const params = Object.fromEntries(
|
|
517
|
+
paramNames.map((n, i) => {
|
|
518
|
+
const value = values[i];
|
|
519
|
+
return [n, value === void 0 ? void 0 : decodeURIComponent(value)];
|
|
520
|
+
})
|
|
521
|
+
);
|
|
522
|
+
return {
|
|
523
|
+
type: "exact",
|
|
524
|
+
route: this.definition,
|
|
525
|
+
params,
|
|
526
|
+
exact: true,
|
|
527
|
+
ascendant: false,
|
|
528
|
+
descendant: false,
|
|
529
|
+
unmatched: false
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
const ancestorRe = this.regexAncestor;
|
|
505
533
|
const ancestorMatch = pathname.match(ancestorRe);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const paramsMatch = exactMatch || (ancestor ? ancestorMatch : null);
|
|
509
|
-
if (paramsMatch) {
|
|
510
|
-
const values = paramsMatch.slice(1, 1 + paramNames.length);
|
|
534
|
+
if (ancestorMatch) {
|
|
535
|
+
const values = ancestorMatch.slice(1, 1 + paramNames.length);
|
|
511
536
|
const params = Object.fromEntries(
|
|
512
537
|
paramNames.map((n, i) => {
|
|
513
538
|
const value = values[i];
|
|
514
539
|
return [n, value === void 0 ? void 0 : decodeURIComponent(value)];
|
|
515
540
|
})
|
|
516
541
|
);
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
542
|
+
return {
|
|
543
|
+
type: "ascendant",
|
|
544
|
+
route: this.definition,
|
|
545
|
+
params,
|
|
546
|
+
exact: false,
|
|
547
|
+
ascendant: true,
|
|
548
|
+
descendant: false,
|
|
549
|
+
unmatched: false
|
|
550
|
+
};
|
|
520
551
|
}
|
|
521
|
-
let descendant = false;
|
|
522
552
|
let descendantMatch = null;
|
|
523
553
|
let descendantCaptureKeys = [];
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
const unmatched = !exact && !ancestor && !descendant;
|
|
535
|
-
if (descendant && descendantMatch) {
|
|
554
|
+
for (const matcher of this.regexDescendantMatchers) {
|
|
555
|
+
const match = pathname.match(matcher.regex);
|
|
556
|
+
if (!match) continue;
|
|
557
|
+
descendantMatch = match;
|
|
558
|
+
descendantCaptureKeys = matcher.captureKeys;
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
if (descendantMatch) {
|
|
536
562
|
const values = descendantMatch.slice(1, 1 + descendantCaptureKeys.length);
|
|
537
|
-
|
|
563
|
+
const params = Object.fromEntries(
|
|
538
564
|
descendantCaptureKeys.map((key, index) => [key, decodeURIComponent(values[index])])
|
|
539
565
|
);
|
|
566
|
+
return {
|
|
567
|
+
type: "descendant",
|
|
568
|
+
route: this.definition,
|
|
569
|
+
params,
|
|
570
|
+
exact: false,
|
|
571
|
+
ascendant: false,
|
|
572
|
+
descendant: true,
|
|
573
|
+
unmatched: false
|
|
574
|
+
};
|
|
540
575
|
}
|
|
541
576
|
return {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
577
|
+
type: "unmatched",
|
|
578
|
+
route: this.definition,
|
|
579
|
+
params: {},
|
|
580
|
+
exact: false,
|
|
581
|
+
ascendant: false,
|
|
582
|
+
descendant: false,
|
|
583
|
+
unmatched: true
|
|
548
584
|
};
|
|
549
585
|
}
|
|
550
586
|
_validateParamsInput(input) {
|
|
@@ -633,90 +669,106 @@ class Route0 {
|
|
|
633
669
|
parse: (value) => this._parseSchemaResult(this._validateParamsInput(value)),
|
|
634
670
|
safeParse: (value) => this._safeParseSchemaResult(this._validateParamsInput(value))
|
|
635
671
|
};
|
|
636
|
-
/** True when path structure is equal (param names are ignored). */
|
|
637
|
-
isSame(other) {
|
|
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
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
672
|
+
// /** True when path structure is equal (param names are ignored). */
|
|
673
|
+
// isSame(other: AnyRoute): boolean {
|
|
674
|
+
// const thisShape = this.routeTokens
|
|
675
|
+
// .map((t) => {
|
|
676
|
+
// if (t.kind === 'static') return `s:${t.value}`
|
|
677
|
+
// if (t.kind === 'param') return `p:${t.optional ? 'o' : 'r'}`
|
|
678
|
+
// return `w:${t.prefix}:${t.optional ? 'o' : 'r'}`
|
|
679
|
+
// })
|
|
680
|
+
// .join('/')
|
|
681
|
+
// const otherRoute = Route0.from(other) as Route0<string, UnknownSearchInput>
|
|
682
|
+
// const otherShape = otherRoute.routeTokens
|
|
683
|
+
// .map((t) => {
|
|
684
|
+
// if (t.kind === 'static') return `s:${t.value}`
|
|
685
|
+
// if (t.kind === 'param') return `p:${t.optional ? 'o' : 'r'}`
|
|
686
|
+
// return `w:${t.prefix}:${t.optional ? 'o' : 'r'}`
|
|
687
|
+
// })
|
|
688
|
+
// .join('/')
|
|
689
|
+
// return thisShape === otherShape
|
|
690
|
+
// }
|
|
691
|
+
// /** Static convenience wrapper for `isSame`. */
|
|
692
|
+
// static isSame(a: AnyRoute | string | undefined, b: AnyRoute | string | undefined): boolean {
|
|
693
|
+
// if (!a) {
|
|
694
|
+
// if (!b) return true
|
|
695
|
+
// return false
|
|
696
|
+
// }
|
|
697
|
+
// if (!b) {
|
|
698
|
+
// return false
|
|
699
|
+
// }
|
|
700
|
+
// return Route0.create(a).isSame(Route0.create(b))
|
|
701
|
+
// }
|
|
702
|
+
// /** True when current route is more specific/deeper than `other`. */
|
|
703
|
+
// isDescendant(other: AnyRoute | string | undefined): boolean {
|
|
704
|
+
// if (!other) return false
|
|
705
|
+
// other = Route0.create(other)
|
|
706
|
+
// // this is a descendant of other if:
|
|
707
|
+
// // - paths are not exactly the same
|
|
708
|
+
// // - other's path is a prefix of this path, matching params as wildcards
|
|
709
|
+
// const getParts = (path: string) => (path === '/' ? ['/'] : path.split('/').filter(Boolean))
|
|
710
|
+
// // Root is ancestor of any non-root; thus any non-root is a descendant of root
|
|
711
|
+
// if (other.definition === '/' && this.definition !== '/') {
|
|
712
|
+
// return true
|
|
713
|
+
// }
|
|
714
|
+
// const thisParts = getParts(this.definition)
|
|
715
|
+
// const otherParts = getParts(other.definition)
|
|
716
|
+
// // A descendant must be deeper
|
|
717
|
+
// if (thisParts.length <= otherParts.length) return false
|
|
718
|
+
// const matchesPatternPart = (patternPart: string, valuePart: string): { match: boolean; wildcard: boolean } => {
|
|
719
|
+
// if (patternPart.startsWith(':')) return { match: true, wildcard: false }
|
|
720
|
+
// const wildcardIndex = patternPart.indexOf('*')
|
|
721
|
+
// if (wildcardIndex >= 0) {
|
|
722
|
+
// const prefix = patternPart.slice(0, wildcardIndex)
|
|
723
|
+
// return { match: prefix.length === 0 || valuePart.startsWith(prefix), wildcard: true }
|
|
724
|
+
// }
|
|
725
|
+
// return { match: patternPart === valuePart, wildcard: false }
|
|
726
|
+
// }
|
|
727
|
+
// for (let i = 0; i < otherParts.length; i++) {
|
|
728
|
+
// const otherPart = otherParts[i]
|
|
729
|
+
// const thisPart = thisParts[i]
|
|
730
|
+
// const result = matchesPatternPart(otherPart, thisPart)
|
|
731
|
+
// if (!result.match) return false
|
|
732
|
+
// if (result.wildcard) return true
|
|
733
|
+
// }
|
|
734
|
+
// // Not equal (depth already ensures not equal)
|
|
735
|
+
// return true
|
|
736
|
+
// }
|
|
737
|
+
// /** True when current route is broader/shallower than `other`. */
|
|
738
|
+
// isAncestor(other: AnyRoute | string | undefined): boolean {
|
|
739
|
+
// if (!other) return false
|
|
740
|
+
// other = Route0.create(other)
|
|
741
|
+
// // this is an ancestor of other if:
|
|
742
|
+
// // - paths are not exactly the same
|
|
743
|
+
// // - this path is a prefix of other path, matching params as wildcards
|
|
744
|
+
// const getParts = (path: string) => (path === '/' ? ['/'] : path.split('/').filter(Boolean))
|
|
745
|
+
// // Root is ancestor of any non-root path
|
|
746
|
+
// if (this.definition === '/' && other.definition !== '/') {
|
|
747
|
+
// return true
|
|
748
|
+
// }
|
|
749
|
+
// const thisParts = getParts(this.definition)
|
|
750
|
+
// const otherParts = getParts(other.definition)
|
|
751
|
+
// // An ancestor must be shallower
|
|
752
|
+
// if (thisParts.length >= otherParts.length) return false
|
|
753
|
+
// const matchesPatternPart = (patternPart: string, valuePart: string): { match: boolean; wildcard: boolean } => {
|
|
754
|
+
// if (patternPart.startsWith(':')) return { match: true, wildcard: false }
|
|
755
|
+
// const wildcardIndex = patternPart.indexOf('*')
|
|
756
|
+
// if (wildcardIndex >= 0) {
|
|
757
|
+
// const prefix = patternPart.slice(0, wildcardIndex)
|
|
758
|
+
// return { match: prefix.length === 0 || valuePart.startsWith(prefix), wildcard: true }
|
|
759
|
+
// }
|
|
760
|
+
// return { match: patternPart === valuePart, wildcard: false }
|
|
761
|
+
// }
|
|
762
|
+
// for (let i = 0; i < thisParts.length; i++) {
|
|
763
|
+
// const thisPart = thisParts[i]
|
|
764
|
+
// const otherPart = otherParts[i]
|
|
765
|
+
// const result = matchesPatternPart(thisPart, otherPart)
|
|
766
|
+
// if (!result.match) return false
|
|
767
|
+
// if (result.wildcard) return true
|
|
768
|
+
// }
|
|
769
|
+
// // Not equal (depth already ensures not equal)
|
|
770
|
+
// return true
|
|
771
|
+
// }
|
|
720
772
|
/** True when two route patterns can match the same concrete URL. */
|
|
721
773
|
isOverlap(other) {
|
|
722
774
|
if (!other) return false;
|
|
@@ -774,21 +826,6 @@ class Route0 {
|
|
|
774
826
|
}
|
|
775
827
|
}
|
|
776
828
|
class Routes {
|
|
777
|
-
static _getNormalizedPathnameFromInput(hrefOrHrefRelOrLocation) {
|
|
778
|
-
if (hrefOrHrefRelOrLocation instanceof URL) {
|
|
779
|
-
return normalizeSlashPath(hrefOrHrefRelOrLocation.pathname);
|
|
780
|
-
}
|
|
781
|
-
if (typeof hrefOrHrefRelOrLocation !== "string") {
|
|
782
|
-
if (typeof hrefOrHrefRelOrLocation.pathname === "string") {
|
|
783
|
-
return normalizeSlashPath(hrefOrHrefRelOrLocation.pathname);
|
|
784
|
-
}
|
|
785
|
-
hrefOrHrefRelOrLocation = hrefOrHrefRelOrLocation.href || hrefOrHrefRelOrLocation.hrefRel;
|
|
786
|
-
}
|
|
787
|
-
const abs = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(hrefOrHrefRelOrLocation);
|
|
788
|
-
const base = abs ? void 0 : "http://example.com";
|
|
789
|
-
const url = new URL(hrefOrHrefRelOrLocation, base);
|
|
790
|
-
return normalizeSlashPath(url.pathname);
|
|
791
|
-
}
|
|
792
829
|
_routes;
|
|
793
830
|
_pathsOrdering;
|
|
794
831
|
_keysOrdering;
|
|
@@ -852,17 +889,17 @@ class Routes {
|
|
|
852
889
|
}
|
|
853
890
|
_getLocation(hrefOrHrefRelOrLocation) {
|
|
854
891
|
const input = hrefOrHrefRelOrLocation;
|
|
855
|
-
const
|
|
892
|
+
const location = Route0.getLocation(input);
|
|
856
893
|
for (const route of this._ordered) {
|
|
857
|
-
if (
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
894
|
+
if (route.isExact(location.pathname, false)) {
|
|
895
|
+
const relation = route.getRelation(input);
|
|
896
|
+
return Object.assign(location, {
|
|
897
|
+
route: route.definition,
|
|
898
|
+
params: relation.params
|
|
899
|
+
});
|
|
863
900
|
}
|
|
864
901
|
}
|
|
865
|
-
return
|
|
902
|
+
return location;
|
|
866
903
|
}
|
|
867
904
|
static makeOrdering(routes) {
|
|
868
905
|
const hydrated = Routes.hydrate(routes);
|