1 | import { pathToRegexp } from './path-to-regex';
|
2 | import { valueEqual } from './location-utils';
|
3 | let cacheCount = 0;
|
4 | const patternCache = {};
|
5 | const cacheLimit = 10000;
|
6 |
|
7 | const compilePath = (pattern, options) => {
|
8 | const cacheKey = `${options.end}${options.strict}`;
|
9 | const cache = patternCache[cacheKey] || (patternCache[cacheKey] = {});
|
10 | const cachePattern = JSON.stringify(pattern);
|
11 | if (cache[cachePattern]) {
|
12 | return cache[cachePattern];
|
13 | }
|
14 | const keys = [];
|
15 | const re = pathToRegexp(pattern, keys, options);
|
16 | const compiledPattern = { re, keys };
|
17 | if (cacheCount < cacheLimit) {
|
18 | cache[cachePattern] = compiledPattern;
|
19 | cacheCount += 1;
|
20 | }
|
21 | return compiledPattern;
|
22 | };
|
23 |
|
24 |
|
25 |
|
26 | export const matchPath = (pathname, options = {}) => {
|
27 | if (typeof options === 'string') {
|
28 | options = { path: options };
|
29 | }
|
30 | const { path = '/', exact = false, strict = false } = options;
|
31 | const { re, keys } = compilePath(path, { end: exact, strict });
|
32 | const match = re.exec(pathname);
|
33 | if (!match) {
|
34 | return null;
|
35 | }
|
36 | const [url, ...values] = match;
|
37 | const isExact = pathname === url;
|
38 | if (exact && !isExact) {
|
39 | return null;
|
40 | }
|
41 | return {
|
42 | path,
|
43 | url: path === '/' && url === '' ? '/' : url,
|
44 | isExact,
|
45 | params: keys.reduce((memo, key, index) => {
|
46 | memo[key.name] = values[index];
|
47 | return memo;
|
48 | }, {})
|
49 | };
|
50 | };
|
51 | export const matchesAreEqual = (a, b) => {
|
52 | if (a == null && b == null) {
|
53 | return true;
|
54 | }
|
55 | if (b == null) {
|
56 | return false;
|
57 | }
|
58 | return a && b &&
|
59 | a.path === b.path &&
|
60 | a.url === b.url &&
|
61 | valueEqual(a.params, b.params);
|
62 | };
|