]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
refactor(matcher): remove class usage
authorEduardo San Martin Morote <posva13@gmail.com>
Sat, 26 Oct 2019 15:32:18 +0000 (16:32 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Sat, 26 Oct 2019 15:32:18 +0000 (16:32 +0100)
__tests__/matcher/ranking.spec.ts
__tests__/matcher/resolve.spec.ts
src/matcher/index.ts
src/matcher/path-ranker.ts
src/router.ts

index ac224c20972e0dd96529a97709c950151df79a97..e820078bff1ef66291d9a499d23eb7c3e4261dbe 100644 (file)
@@ -1,4 +1,4 @@
-import { createRouteMatcher } from '../../src/matcher/path-ranker'
+import { createRouteRecordMatcher } from '../../src/matcher/path-ranker'
 import { RegExpOptions } from 'path-to-regexp'
 import { RouteComponent } from '../../src/types'
 import { RouteRecordMatcher } from '../../src/matcher/types'
@@ -10,7 +10,7 @@ function stringifyOptions(options: any) {
   return Object.keys(options).length ? ` (${JSON.stringify(options)})` : ''
 }
 
-describe('createRouteMatcher', () => {
+describe('createRouteRecordMatcher', () => {
   function checkPathOrder(
     paths: Array<string | [string, RegExpOptions]>,
     options: RegExpOptions = {}
@@ -29,7 +29,7 @@ describe('createRouteMatcher', () => {
       // routes with the same ranking
       .reverse()
       .map(([path, options]) => ({
-        ...createRouteMatcher(
+        ...createRouteRecordMatcher(
           {
             // @ts-ignore types are correct
             path,
index 034a5381b80c34a3eaea61ee4ec37d9c273f4d0c..0b8dd4c1dcc11ae45574b6f131cffafcaa39358a 100644 (file)
@@ -1,4 +1,4 @@
-import { RouterMatcher } from '../../src/matcher'
+import { createRouterMatcher } from '../../src/matcher'
 import {
   START_LOCATION_NORMALIZED,
   RouteComponent,
@@ -12,10 +12,6 @@ import { normalizeRouteRecord } from '../utils'
 // @ts-ignore
 const component: RouteComponent = null
 
-function createRouterMatcher(records: RouteRecord[]) {
-  return new RouterMatcher(records)
-}
-
 // for normalized records
 const components = { default: component }
 
index 2125753127b54ea0a8d3c6a60e479e8c2c9bb6f0..b2aae6164318312a415b226ff79c845f6d759b28 100644 (file)
@@ -9,19 +9,21 @@ import {
   // MatchedRouteRecord,
 } from '../types'
 import { NoRouteMatchError, InvalidRouteMatch } from '../errors'
-import { createRouteMatcher, normalizeRouteRecord } from './path-ranker'
+import { createRouteRecordMatcher, normalizeRouteRecord } from './path-ranker'
 import { RouteRecordMatcher } from './types'
 
-export class RouterMatcher {
-  private matchers: RouteRecordMatcher[] = []
+interface RouterMatcher {
+  addRoute: (record: Readonly<RouteRecord>, parent?: RouteRecordMatcher) => void
+  resolve: (
+    location: Readonly<MatcherLocation>,
+    currentLocation: Readonly<MatcherLocationNormalized>
+  ) => MatcherLocationNormalized | MatcherLocationRedirect
+}
 
-  constructor(routes: RouteRecord[]) {
-    for (const route of routes) {
-      this.addRouteRecord(route)
-    }
-  }
+export function createRouterMatcher(routes: RouteRecord[]): RouterMatcher {
+  const matchers: RouteRecordMatcher[] = []
 
-  private addRouteRecord(
+  function addRoute(
     record: Readonly<RouteRecord>,
     parent?: RouteRecordMatcher
   ): void {
@@ -58,11 +60,15 @@ export class RouterMatcher {
 
     for (const normalizedRecord of normalizedRecords) {
       // create the object before hand so it can be passed to children
-      const matcher = createRouteMatcher(normalizedRecord, parent, options)
+      const matcher = createRouteRecordMatcher(
+        normalizedRecord,
+        parent,
+        options
+      )
 
       if ('children' in record && record.children) {
         for (const childRecord of record.children) {
-          this.addRouteRecord(childRecord, matcher)
+          addRoute(childRecord, matcher)
         }
         // TODO: the parent is special, we should match their children. They
         // reference to the parent so we can render the parent
@@ -70,28 +76,22 @@ export class RouterMatcher {
         // matcher.score = -10
       }
 
-      this.insertMatcher(matcher)
+      insertMatcher(matcher)
     }
   }
 
-  private insertMatcher(matcher: RouteRecordMatcher) {
+  function insertMatcher(matcher: RouteRecordMatcher) {
     let i = 0
-    while (i < this.matchers.length && matcher.score <= this.matchers[i].score)
-      i++
-    this.matchers.splice(i, 0, matcher)
+    while (i < matchers.length && matcher.score <= matchers[i].score) i++
+    matchers.splice(i, 0, matcher)
   }
 
   /**
-   * Resolve a location without doing redirections so it can be used for anchors
-   */
-  resolveAsPath() {}
-
-  /**
-   * Transforms a MatcherLocation object into a normalized location
+   * Resolves a location. Gives access to the route record that corresponds to the actual path as well as filling the corresponding params objects
    * @param location MatcherLocation to resolve to a url
    * @param currentLocation MatcherLocationNormalized of the current location
    */
-  resolve(
+  function resolve(
     location: Readonly<MatcherLocation>,
     currentLocation: Readonly<MatcherLocationNormalized>
   ): MatcherLocationNormalized | MatcherLocationRedirect {
@@ -101,7 +101,7 @@ export class RouterMatcher {
     let name: MatcherLocationNormalized['name']
 
     if ('name' in location && location.name) {
-      matcher = this.matchers.find(m => m.record.name === location.name)
+      matcher = matchers.find(m => m.record.name === location.name)
 
       if (!matcher) throw new NoRouteMatchError(currentLocation, location)
 
@@ -127,7 +127,7 @@ export class RouterMatcher {
         }
       }
     } else if ('path' in location) {
-      matcher = this.matchers.find(m => m.re.test(location.path))
+      matcher = matchers.find(m => m.re.test(location.path))
 
       // TODO: if no matcher, return the location with an empty matched array
       // to allow non existent matches
@@ -187,8 +187,8 @@ export class RouterMatcher {
     } else {
       // match by name or path of current route
       matcher = currentLocation.name
-        ? this.matchers.find(m => m.record.name === currentLocation.name)
-        : this.matchers.find(m => m.re.test(currentLocation.path))
+        ? matchers.find(m => m.record.name === currentLocation.name)
+        : matchers.find(m => m.re.test(currentLocation.path))
       if (!matcher) throw new NoRouteMatchError(currentLocation, location)
       name = matcher.record.name
       params = location.params || currentLocation.params
@@ -217,4 +217,11 @@ export class RouterMatcher {
       meta: matcher.record.meta || {},
     }
   }
+
+  // add initial routes
+  for (const route of routes) {
+    addRoute(route)
+  }
+
+  return { addRoute, resolve }
 }
index 2c13f325259934a9eaa193fda6ed7fe3e7ec6259..8e2c1d249f4bbe6d1aa8789940f3c93aca467f8e 100644 (file)
@@ -89,7 +89,7 @@ const enum PathScore {
 // allows to check if the user provided a custom regexp
 const isDefaultPathRegExpRE = /^\[\^[^\]]+\]\+\?$/
 
-export function createRouteMatcher(
+export function createRouteRecordMatcher(
   record: Readonly<NormalizedRouteRecord>,
   parent: RouteRecordMatcher | void,
   options: pathToRegexp.RegExpOptions
index ab20592eb95822ff65f4c66b81f56b5ffbd2f7a7..72beb9818a7169fb0d6ddedaefa168bcc90a771d 100644 (file)
@@ -6,7 +6,7 @@ import {
   HistoryLocationNormalized,
   START,
 } from './history/common'
-import { RouterMatcher } from './matcher'
+import { createRouterMatcher } from './matcher'
 import {
   RouteLocation,
   RouteRecord,
@@ -53,7 +53,7 @@ type ErrorHandler = (error: any) => any
 type OnReadyCallback = [() => void, (reason?: any) => void]
 export class Router {
   protected history: RouterHistory
-  private matcher: RouterMatcher
+  private matcher: ReturnType<typeof createRouterMatcher>
   private beforeGuards: NavigationGuard[] = []
   private afterGuards: PostNavigationGuard[] = []
   currentRoute: Readonly<RouteLocationNormalized> = START_LOCATION_NORMALIZED
@@ -70,7 +70,7 @@ export class Router {
     // this.history.ensureLocation()
     this.scrollBehavior = options.scrollBehavior
 
-    this.matcher = new RouterMatcher(options.routes)
+    this.matcher = createRouterMatcher(options.routes)
 
     this.history.listen(async (to, from, info) => {
       const matchedRoute = this.resolveLocation(to, this.currentRoute)