All files index.js

100% Statements 27/27
100% Branches 15/15
100% Functions 7/7
100% Lines 25/25
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74      1x       1x 7x 3x   4x     1x 5x   5x                   12x       12x 24x 1x   23x 2x   21x       21x 7x         7x     14x       11x 7x     11x     4x     4x 4x              
import { createElement } from 'react';
import { matchPath, withRouter } from 'react-router';
 
const DEFAULT_MATCH_OPTIONS = { exact: true };
 
// if user is passing a function (component) as a breadcrumb, make sure we
// pass the match object into it. Else just return the string.
const renderer = ({ breadcrumb, match }) => {
  if (typeof breadcrumb === 'function') {
    return createElement(breadcrumb, { match });
  }
  return breadcrumb;
};
 
export const getBreadcrumbs = ({ routes, pathname }) => {
  const matches = [];
 
  pathname
    // remove trailing slash "/" from pathname (avoids multiple of the same match)
    .replace(/\/$/, '')
    // split pathname into sections
    .split('/')
    // reduce over the sections and find matches from `routes` prop
    .reduce((previous, current) => {
      // combine the last route section with the current
      // ex `pathname = /1/2/3 results in match checks for
      // `/1`, `/1/2`, `/1/2/3`
      const pathSection = !current ? '/' : `${previous}/${current}`;
 
      let breadcrumbMatch;
 
      routes.some(({ breadcrumb, matchOptions, path }) => {
        if (!path) {
          throw new Error('withBreadcrumbs: `path` must be provided in every route object');
        }
        if (!breadcrumb) {
          return false;
        }
        const match = matchPath(pathSection, { ...(matchOptions || DEFAULT_MATCH_OPTIONS), path });
 
        // if a route match is found ^ break out of the loop with a rendered breadcumb
        // and match object to add to the `matches` array
        if (match) {
          breadcrumbMatch = {
            breadcrumb: renderer({ breadcrumb, match }),
            path,
            match,
          };
          return true;
        }
 
        return false;
      });
 
      /* istanbul ignore else */
      if (breadcrumbMatch) {
        matches.push(breadcrumbMatch);
      }
 
      return pathSection === '/' ? '' : pathSection;
    }, null);
 
  return matches;
};
 
export const withBreadcrumbs = routes => Component => withRouter(props =>
  createElement(Component, {
    ...props,
    breadcrumbs: getBreadcrumbs({
      pathname: props.location.pathname,
      routes,
    }),
  }));