UNPKG

react-router

Version:

A complete routing library for React.js

178 lines (159 loc) • 5.78 kB
'use strict'; import warning from 'warning'; import { loopAsync } from './AsyncUtils'; import { matchPattern } from './PatternUtils'; import { createRoutes } from './RouteUtils'; function getChildRoutes(route, location, callback) { if (route.childRoutes) { callback(null, route.childRoutes); } else if (route.getChildRoutes) { route.getChildRoutes(location, function (error, childRoutes) { callback(error, !error && createRoutes(childRoutes)); }); } else { callback(); } } function getIndexRoute(route, location, callback) { if (route.indexRoute) { callback(null, route.indexRoute); } else if (route.getIndexRoute) { route.getIndexRoute(location, function (error, indexRoute) { callback(error, !error && createRoutes(indexRoute)[0]); }); } else if (route.childRoutes) { (function () { var pathless = route.childRoutes.filter(function (obj) { return !obj.hasOwnProperty('path'); }); loopAsync(pathless.length, function (index, next, done) { getIndexRoute(pathless[index], location, function (error, indexRoute) { if (error || indexRoute) { var routes = [pathless[index]].concat(Array.isArray(indexRoute) ? indexRoute : [indexRoute]); done(error, routes); } else { next(); } }); }, function (err, routes) { callback(null, routes); }); })(); } else { callback(); } } function assignParams(params, paramNames, paramValues) { return paramNames.reduce(function (params, paramName, index) { var paramValue = paramValues && paramValues[index]; if (Array.isArray(params[paramName])) { params[paramName].push(paramValue); } else if (paramName in params) { params[paramName] = [params[paramName], paramValue]; } else { params[paramName] = paramValue; } return params; }, params); } function createParams(paramNames, paramValues) { return assignParams({}, paramNames, paramValues); } function matchRouteDeep(route, location, remainingPathname, paramNames, paramValues, callback) { var pattern = route.path || ''; if (pattern.charAt(0) === '/') { remainingPathname = location.pathname; paramNames = []; paramValues = []; } if (remainingPathname !== null) { var matched = matchPattern(pattern, remainingPathname); remainingPathname = matched.remainingPathname; paramNames = [].concat(paramNames, matched.paramNames); paramValues = [].concat(paramValues, matched.paramValues); if (remainingPathname === '' && route.path) { var _ret2 = (function () { var match = { routes: [route], params: createParams(paramNames, paramValues) }; getIndexRoute(route, location, function (error, indexRoute) { if (error) { callback(error); } else { if (Array.isArray(indexRoute)) { var _match$routes; process.env.NODE_ENV !== 'production' ? warning(indexRoute.every(function (route) { return !route.path; }), 'Index routes should not have paths') : undefined; (_match$routes = match.routes).push.apply(_match$routes, indexRoute); } else if (indexRoute) { process.env.NODE_ENV !== 'production' ? warning(!indexRoute.path, 'Index routes should not have paths') : undefined; match.routes.push(indexRoute); } callback(null, match); } }); return { v: undefined }; })(); if (typeof _ret2 === 'object') return _ret2.v; } } if (remainingPathname != null || route.childRoutes) { // Either a) this route matched at least some of the path or b) // we don't have to load this route's children asynchronously. In // either case continue checking for matches in the subtree. getChildRoutes(route, location, function (error, childRoutes) { if (error) { callback(error); } else if (childRoutes) { // Check the child routes to see if any of them match. matchRoutes(childRoutes, location, function (error, match) { if (error) { callback(error); } else if (match) { // A child route matched! Augment the match and pass it up the stack. match.routes.unshift(route); callback(null, match); } else { callback(); } }, remainingPathname, paramNames, paramValues); } else { callback(); } }); } else { callback(); } } /** * Asynchronously matches the given location to a set of routes and calls * callback(error, state) when finished. The state object will have the * following properties: * * - routes An array of routes that matched, in hierarchical order * - params An object of URL parameters * * Note: This operation may finish synchronously if no routes have an * asynchronous getChildRoutes method. */ function matchRoutes(routes, location, callback) { var remainingPathname = arguments.length <= 3 || arguments[3] === undefined ? location.pathname : arguments[3]; var paramNames = arguments.length <= 4 || arguments[4] === undefined ? [] : arguments[4]; var paramValues = arguments.length <= 5 || arguments[5] === undefined ? [] : arguments[5]; return (function () { loopAsync(routes.length, function (index, next, done) { matchRouteDeep(routes[index], location, remainingPathname, paramNames, paramValues, function (error, match) { if (error || match) { done(error, match); } else { next(); } }); }, callback); })(); } export default matchRoutes;