react-router
Version:
A complete routing library for React
152 lines (124 loc) • 4.51 kB
JavaScript
exports.__esModule = true;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
exports.default = isActive;
var _PatternUtils = require('./PatternUtils');
function deepEqual(a, b) {
if (a == b) return true;
if (a == null || b == null) return false;
if (Array.isArray(a)) {
return Array.isArray(b) && a.length === b.length && a.every(function (item, index) {
return deepEqual(item, b[index]);
});
}
if ((typeof a === 'undefined' ? 'undefined' : _typeof(a)) === 'object') {
for (var p in a) {
if (!Object.prototype.hasOwnProperty.call(a, p)) {
continue;
}
if (a[p] === undefined) {
if (b[p] !== undefined) {
return false;
}
} else if (!Object.prototype.hasOwnProperty.call(b, p)) {
return false;
} else if (!deepEqual(a[p], b[p])) {
return false;
}
}
return true;
}
return String(a) === String(b);
}
/**
* Returns true if the current pathname matches the supplied one, net of
* leading and trailing slash normalization. This is sufficient for an
* indexOnly route match.
*/
function pathIsActive(pathname, currentPathname) {
// Normalize leading slash for consistency. Leading slash on pathname has
// already been normalized in isActive. See caveat there.
if (currentPathname.charAt(0) !== '/') {
currentPathname = '/' + currentPathname;
}
// Normalize the end of both path names too. Maybe `/foo/` shouldn't show
// `/foo` as active, but in this case, we would already have failed the
// match.
if (pathname.charAt(pathname.length - 1) !== '/') {
pathname += '/';
}
if (currentPathname.charAt(currentPathname.length - 1) !== '/') {
currentPathname += '/';
}
return currentPathname === pathname;
}
/**
* Returns true if the given pathname matches the active routes and params.
*/
function routeIsActive(pathname, routes, params) {
var remainingPathname = pathname,
paramNames = [],
paramValues = [];
// for...of would work here but it's probably slower post-transpilation.
for (var i = 0, len = routes.length; i < len; ++i) {
var route = routes[i];
var pattern = route.path || '';
if (pattern.charAt(0) === '/') {
remainingPathname = pathname;
paramNames = [];
paramValues = [];
}
if (remainingPathname !== null && pattern) {
var matched = (0, _PatternUtils.matchPattern)(pattern, remainingPathname);
if (matched) {
remainingPathname = matched.remainingPathname;
paramNames = [].concat(paramNames, matched.paramNames);
paramValues = [].concat(paramValues, matched.paramValues);
} else {
remainingPathname = null;
}
if (remainingPathname === '') {
// We have an exact match on the route. Just check that all the params
// match.
// FIXME: This doesn't work on repeated params.
return paramNames.every(function (paramName, index) {
return String(paramValues[index]) === String(params[paramName]);
});
}
}
}
return false;
}
/**
* Returns true if all key/value pairs in the given query are
* currently active.
*/
function queryIsActive(query, activeQuery) {
if (activeQuery == null) return query == null;
if (query == null) return true;
return deepEqual(query, activeQuery);
}
/**
* Returns true if a <Link> to the given pathname/query combination is
* currently active.
*/
function isActive(_ref, indexOnly, currentLocation, routes, params) {
var pathname = _ref.pathname,
query = _ref.query;
if (currentLocation == null) return false;
// TODO: This is a bit ugly. It keeps around support for treating pathnames
// without preceding slashes as absolute paths, but possibly also works
// around the same quirks with basenames as in matchRoutes.
if (pathname.charAt(0) !== '/') {
pathname = '/' + pathname;
}
if (!pathIsActive(pathname, currentLocation.pathname)) {
// The path check is necessary and sufficient for indexOnly, but otherwise
// we still need to check the routes.
if (indexOnly || !routeIsActive(pathname, routes, params)) {
return false;
}
}
return queryIsActive(query, currentLocation.query);
}
module.exports = exports['default'];
;