@nent/core
Version:
73 lines (72 loc) • 1.94 kB
JavaScript
/*!
* NENT 2022
*/
/* istanbul ignore file */
import { valueEqual } from './location';
import { pathToRegexp } from './path-regex';
let cacheCount = 0;
const patternCache = {};
const cacheLimit = 10000;
// Memoized function for creating the path match regex
const compilePath = (pattern, options) => {
const cacheKey = `${options.end}${options.strict}`;
const cache = patternCache[cacheKey] || (patternCache[cacheKey] = {});
const cachePattern = JSON.stringify(pattern instanceof RegExp ? pattern.source : pattern);
if (cache[cachePattern]) {
return cache[cachePattern];
}
const keys = [];
const re = pathToRegexp(pattern, keys, options);
const compiledPattern = { re, keys };
if (cacheCount < cacheLimit) {
cache[cachePattern] = compiledPattern;
cacheCount += 1;
}
return compiledPattern;
};
/**
* Public API for matching a URL pathname to a path pattern.
*/
export function matchPath(location, options = {}) {
if (typeof options === 'string') {
options = { path: options };
}
const { pathname } = location;
const { path = '/', exact = false, strict = false } = options;
const { re, keys } = compilePath(path, { end: exact, strict });
const match = re.exec(pathname);
if (!match) {
return null;
}
const [url, ...values] = match;
const isExact = pathname === url;
if (exact && !isExact) {
return null;
}
const result = {
path,
url: path === '/' && url === '' ? '/' : url,
isExact,
params: keys.reduce((memo, key, index) => {
memo[key.name] = values[index];
return memo;
}, {}),
};
if (result.isExact) {
Object.assign(location.params, result.params);
}
return result;
}
export const matchesAreEqual = (a, b) => {
if (a === null && b === null) {
return true;
}
if (b === null) {
return false;
}
return (a &&
b &&
a.path === b.path &&
a.url === b.url &&
valueEqual(a.params, b.params));
};