import React from 'react' import warning from './routerWarning' function isValidChild(object) { return object == null || React.isValidElement(object) } export function isReactChildren(object) { return isValidChild(object) || (Array.isArray(object) && object.every(isValidChild)) } function checkPropTypes(componentName, propTypes, props) { componentName = componentName || 'UnknownComponent' for (const propName in propTypes) { if (Object.prototype.hasOwnProperty.call(propTypes, propName)) { const error = propTypes[propName](props, propName, componentName) /* istanbul ignore if: error logging */ if (error instanceof Error) warning(false, error.message) } } } function createRoute(defaultProps, props) { return { ...defaultProps, ...props } } export function createRouteFromReactElement(element) { const type = element.type const route = createRoute(type.defaultProps, element.props) if (type.propTypes) checkPropTypes(type.displayName || type.name, type.propTypes, route) if (route.children) { const childRoutes = createRoutesFromReactChildren(route.children, route) if (childRoutes.length) route.childRoutes = childRoutes delete route.children } return route } /** * Creates and returns a routes object from the given ReactChildren. JSX * provides a convenient way to visualize how routes in the hierarchy are * nested. * * import { Route, createRoutesFromReactChildren } from 'react-router' * * const routes = createRoutesFromReactChildren( * * * * * ) * * Note: This method is automatically used when you provide children * to a component. */ export function createRoutesFromReactChildren(children, parentRoute) { const routes = [] React.Children.forEach(children, function (element) { if (React.isValidElement(element)) { // Component classes may have a static create* method. if (element.type.createRouteFromReactElement) { const route = element.type.createRouteFromReactElement(element, parentRoute) if (route) routes.push(route) } else { routes.push(createRouteFromReactElement(element)) } } }) return routes } /** * Creates and returns an array of routes from the given object which * may be a JSX route, a plain object route, or an array of either. */ export function createRoutes(routes) { if (isReactChildren(routes)) { routes = createRoutesFromReactChildren(routes) } else if (routes && !Array.isArray(routes)) { routes = [ routes ] } return routes }