From: Eduardo San Martin Morote Date: Tue, 21 Apr 2020 16:33:57 +0000 (+0200) Subject: refactor(utils): move location utils to its file X-Git-Tag: v4.0.0-alpha.8~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=17fa4cfb7ca31a92846807c40f62943ac39a01db;p=thirdparty%2Fvuejs%2Frouter.git refactor(utils): move location utils to its file --- diff --git a/__tests__/location.spec.ts b/__tests__/location.spec.ts index e5a9f93e..07222f32 100644 --- a/__tests__/location.spec.ts +++ b/__tests__/location.spec.ts @@ -4,8 +4,8 @@ import { parseURL as originalParseURL, stringifyURL as originalStringifyURL, stripBase, + isSameLocationObject, } from '../src/utils/location' -import { isSameLocationObject } from '../src/utils' describe('parseURL', () => { let parseURL = originalParseURL.bind(null, parseQuery) diff --git a/src/components/Link.ts b/src/components/Link.ts index d6295f34..b83e8fea 100644 --- a/src/components/Link.ts +++ b/src/components/Link.ts @@ -9,7 +9,7 @@ import { Component, } from 'vue' import { RouteLocationRaw, VueUseOptions, RouteLocation } from '../types' -import { isSameLocationObject, isSameRouteRecord } from '../utils' +import { isSameLocationObject, isSameRouteRecord } from '../utils/location' import { routerKey, routeLocationKey } from '../utils/injectionSymbols' import { RouteRecord } from '../matcher/types' diff --git a/src/router.ts b/src/router.ts index 3bb36841..4063b382 100644 --- a/src/router.ts +++ b/src/router.ts @@ -31,12 +31,7 @@ import { NavigationFailure, NavigationRedirectError, } from './errors' -import { - applyToParams, - isSameRouteRecord, - isSameLocationObject, - isBrowser, -} from './utils' +import { applyToParams, isBrowser } from './utils' import { useCallbacks } from './utils/callbacks' import { encodeParam, decode } from './utils/encoding' import { @@ -59,7 +54,7 @@ import { RouteRecord, RouteRecordNormalized } from './matcher/types' import { Link } from './components/Link' import { View } from './components/View' import { routerKey, routeLocationKey } from './utils/injectionSymbols' -import { parseURL, stringifyURL } from './utils/location' +import { parseURL, stringifyURL, isSameRouteLocation } from './utils/location' import { extractComponentsGuards, guardToPromiseFn } from './navigationGuards' /** @@ -756,18 +751,3 @@ function extractChangingRecords( return [leavingRecords, updatingRecords, enteringRecords] } - -// TODO: move to utils and test -function isSameRouteLocation(a: RouteLocation, b: RouteLocation): boolean { - let aLastIndex = a.matched.length - 1 - let bLastIndex = b.matched.length - 1 - - return ( - aLastIndex > -1 && - aLastIndex === bLastIndex && - isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) && - isSameLocationObject(a.params, b.params) && - isSameLocationObject(a.query, b.query) && - a.hash === b.hash - ) -} diff --git a/src/utils/index.ts b/src/utils/index.ts index 1b1f4658..139e3f56 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,11 +1,4 @@ -import { - RouteLocationNormalized, - RouteParams, - RouteComponent, - RouteParamValue, -} from '../types' -import { RouteRecord } from '../matcher/types' -import { LocationQueryValue } from './query' +import { RouteParams, RouteComponent } from '../types' import { hasSymbol } from './injectionSymbols' export * from './env' @@ -27,71 +20,3 @@ export function applyToParams( return newParams } - -export function isSameRouteRecord(a: RouteRecord, b: RouteRecord): boolean { - // since the original record has an undefined value for aliasOf - // but all aliases point to the original record, this will always compare - // the original record - return (a.aliasOf || a) === (b.aliasOf || b) -} - -export function isSameLocationObject( - a: RouteLocationNormalized['query'], - b: RouteLocationNormalized['query'] -): boolean -export function isSameLocationObject( - a: RouteLocationNormalized['params'], - b: RouteLocationNormalized['params'] -): boolean -export function isSameLocationObject( - a: RouteLocationNormalized['query' | 'params'], - b: RouteLocationNormalized['query' | 'params'] -): boolean { - if (Object.keys(a).length !== Object.keys(b).length) return false - - for (let key in a) { - if (!isSameLocationObjectValue(a[key], b[key])) return false - } - - return true -} - -function isSameLocationObjectValue( - a: LocationQueryValue | LocationQueryValue[], - b: LocationQueryValue | LocationQueryValue[] -): boolean -function isSameLocationObjectValue( - a: RouteParamValue | RouteParamValue[], - b: RouteParamValue | RouteParamValue[] -): boolean -function isSameLocationObjectValue( - a: - | LocationQueryValue - | LocationQueryValue[] - | RouteParamValue - | RouteParamValue[], - b: - | LocationQueryValue - | LocationQueryValue[] - | RouteParamValue - | RouteParamValue[] -): boolean { - return Array.isArray(a) - ? isEquivalentArray(a, b) - : Array.isArray(b) - ? isEquivalentArray(b, a) - : a === b -} - -/** - * Check if two arrays are the same or if an array with one single entry is the - * same as another primitive value. Used to check query and parameters - * - * @param a array of values - * @param b array of values or a single value - */ -function isEquivalentArray(a: T[], b: T[] | T): boolean { - return Array.isArray(b) - ? a.length === b.length && a.every((value, i) => value === b[i]) - : a.length === 1 && a[0] === b -} diff --git a/src/utils/location.ts b/src/utils/location.ts index 1dc7773c..fb82350d 100644 --- a/src/utils/location.ts +++ b/src/utils/location.ts @@ -1,13 +1,27 @@ -import { LocationQuery, LocationQueryRaw } from './query' +import { LocationQuery, LocationQueryRaw, LocationQueryValue } from './query' +import { + RouteLocation, + RouteLocationNormalized, + RouteParamValue, +} from '../types' +import { RouteRecord } from '../matcher/types' -export interface LocationNormalized { +/** + * Location object returned by {@link `parseURL`}. + * @internal + */ +interface LocationNormalized { path: string fullPath: string hash: string query: LocationQuery } -export interface LocationPartial { +/** + * Location object accepted by {@link `stringifyURL`}. + * @internal + */ +interface LocationPartial { path: string query?: LocationQueryRaw hash?: string @@ -84,3 +98,103 @@ export function stripBase(pathname: string, base: string): string { if (!base || pathname.indexOf(base) !== 0) return pathname return pathname.replace(base, '') || '/' } + +/** + * Checks if two RouteLocation are equal. This means that both locations are + * pointing towards the same {@link RouteRecord} and that all `params`, `query` + * parameters and `hash` are the same + * + * @param a first {@link RouteLocation} + * @param b second {@link RouteLocation} + */ +export function isSameRouteLocation( + a: RouteLocation, + b: RouteLocation +): boolean { + let aLastIndex = a.matched.length - 1 + let bLastIndex = b.matched.length - 1 + + return ( + aLastIndex > -1 && + aLastIndex === bLastIndex && + isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) && + isSameLocationObject(a.params, b.params) && + isSameLocationObject(a.query, b.query) && + a.hash === b.hash + ) +} + +/** + * Check if two `RouteRecords` are equal. Takes into account aliases: they are + * considered equal to the `RouteRecord` they are aliasing. + * + * @param a first {@link RouteRecord} + * @param b second {@link RouteRecord} + */ +export function isSameRouteRecord(a: RouteRecord, b: RouteRecord): boolean { + // since the original record has an undefined value for aliasOf + // but all aliases point to the original record, this will always compare + // the original record + return (a.aliasOf || a) === (b.aliasOf || b) +} + +export function isSameLocationObject( + a: RouteLocationNormalized['query'], + b: RouteLocationNormalized['query'] +): boolean +export function isSameLocationObject( + a: RouteLocationNormalized['params'], + b: RouteLocationNormalized['params'] +): boolean +export function isSameLocationObject( + a: RouteLocationNormalized['query' | 'params'], + b: RouteLocationNormalized['query' | 'params'] +): boolean { + if (Object.keys(a).length !== Object.keys(b).length) return false + + for (let key in a) { + if (!isSameLocationObjectValue(a[key], b[key])) return false + } + + return true +} + +function isSameLocationObjectValue( + a: LocationQueryValue | LocationQueryValue[], + b: LocationQueryValue | LocationQueryValue[] +): boolean +function isSameLocationObjectValue( + a: RouteParamValue | RouteParamValue[], + b: RouteParamValue | RouteParamValue[] +): boolean +function isSameLocationObjectValue( + a: + | LocationQueryValue + | LocationQueryValue[] + | RouteParamValue + | RouteParamValue[], + b: + | LocationQueryValue + | LocationQueryValue[] + | RouteParamValue + | RouteParamValue[] +): boolean { + return Array.isArray(a) + ? isEquivalentArray(a, b) + : Array.isArray(b) + ? isEquivalentArray(b, a) + : a === b +} + +/** + * Check if two arrays are the same or if an array with one single entry is the + * same as another primitive value. Used to check query and parameters + * + * @param a array of values + * @param b array of values or a single value + */ +function isEquivalentArray(a: T[], b: T[] | T): boolean { + return Array.isArray(b) + ? a.length === b.length && a.every((value, i) => value === b[i]) + : a.length === 1 && a[0] === b +}