matchPath.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import pathToRegexp from "path-to-regexp";
  2. const cache = {};
  3. const cacheLimit = 10000;
  4. let cacheCount = 0;
  5. function compilePath(path, options) {
  6. const cacheKey = `${options.end}${options.strict}${options.sensitive}`;
  7. const pathCache = cache[cacheKey] || (cache[cacheKey] = {});
  8. if (pathCache[path]) return pathCache[path];
  9. const keys = [];
  10. const regexp = pathToRegexp(path, keys, options);
  11. const result = { regexp, keys };
  12. if (cacheCount < cacheLimit) {
  13. pathCache[path] = result;
  14. cacheCount++;
  15. }
  16. return result;
  17. }
  18. /**
  19. * Public API for matching a URL pathname to a path.
  20. */
  21. function matchPath(pathname, options = {}) {
  22. if (typeof options === "string" || Array.isArray(options)) {
  23. options = { path: options };
  24. }
  25. const { path, exact = false, strict = false, sensitive = false } = options;
  26. const paths = [].concat(path);
  27. return paths.reduce((matched, path) => {
  28. if (!path && path !== "") return null;
  29. if (matched) return matched;
  30. const { regexp, keys } = compilePath(path, {
  31. end: exact,
  32. strict,
  33. sensitive
  34. });
  35. const match = regexp.exec(pathname);
  36. if (!match) return null;
  37. const [url, ...values] = match;
  38. const isExact = pathname === url;
  39. if (exact && !isExact) return null;
  40. return {
  41. path, // the path used to match
  42. url: path === "/" && url === "" ? "/" : url, // the matched portion of the URL
  43. isExact, // whether or not we matched exactly
  44. params: keys.reduce((memo, key, index) => {
  45. memo[key.name] = values[index];
  46. return memo;
  47. }, {})
  48. };
  49. }, null);
  50. }
  51. export default matchPath;