]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
wip: RouterMatcher
authorEduardo San Martin Morote <posva13@gmail.com>
Fri, 29 Mar 2019 19:26:29 +0000 (20:26 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Fri, 29 Mar 2019 19:26:29 +0000 (20:26 +0100)
src/index.ts
src/matcher.ts [new file with mode: 0644]
src/types/index.ts

index c6899dd1faba9083f441b2e98c265f695df71871..23b5307095daf4cc80a3ba07b936383e8d6f3e51 100644 (file)
@@ -1,6 +1,11 @@
 import BaseHistory from './history/base'
 import pathToRegexp from 'path-to-regexp'
-import { Location, RouteRecord, ParamsType, START_RECORD } from './types/index'
+import {
+  RouterLocation,
+  RouteRecord,
+  ParamsType,
+  START_RECORD,
+} from './types/index'
 
 interface RouterOptions {
   history: BaseHistory
@@ -45,7 +50,7 @@ export class Router {
    * Trigger a navigation, should resolve all guards first
    * @param to Where to go
    */
-  push(to: Location) {
+  push(to: RouterLocation) {
     // TODO: resolve URL
     const path = this.resolve(to)
     // TODO: call hooks, guards
@@ -59,14 +64,14 @@ export class Router {
     )
   }
 
-  getRouteRecord(location: Location) {}
+  getRouteRecord(location: RouterLocation) {}
 
   /**
-   * Transforms a Location object into a URL string. If a string is
+   * Transforms a RouterLocation object into a URL string. If a string is
    * passed, it returns the string itself
-   * @param location Location to resolve to a url
+   * @param location RouterLocation to resolve to a url
    */
-  resolve(location: Readonly<Location>): string {
+  resolve(location: Readonly<RouterLocation>): string {
     if (typeof location === 'string') return location
     if ('path' in location) {
       // TODO: convert query, hash, warn params
diff --git a/src/matcher.ts b/src/matcher.ts
new file mode 100644 (file)
index 0000000..55f8870
--- /dev/null
@@ -0,0 +1,80 @@
+import pathToRegexp from 'path-to-regexp'
+import {
+  RouteRecord,
+  ParamsType,
+  START_RECORD,
+  RouterLocation,
+  RouterLocationNormalized,
+} from './types/index'
+
+// TODO: rename
+interface RouteMatcher {
+  re: RegExp
+  resolve: (params: ParamsType) => string
+  record: RouteRecord
+  keys: string[]
+}
+
+function generateMatcher(record: RouteRecord) {
+  const keys: pathToRegexp.Key[] = []
+  // TODO: if children use option end: false ?
+  const re = pathToRegexp(record.path, keys)
+  return {
+    re,
+    resolve: pathToRegexp.compile(record.path),
+    keys: keys.map(k => '' + k.name),
+    record,
+  }
+}
+
+const START_MATCHER = generateMatcher(START_RECORD)
+
+export class RouterMatcher {
+  private matchers: RouteMatcher[] = []
+
+  constructor(routes: RouteRecord[]) {
+    this.matchers = routes.map(generateMatcher)
+  }
+
+  /**
+   * Normalize a RouterLocation into an object that is easier to handle
+   * @param location location to normalize
+   * @param currentLocation current location, to reuse params and location
+   */
+  normalize(
+    location: Readonly<RouterLocation>,
+    currentLocation: Readonly<RouterLocationNormalized>
+  ): RouterLocationNormalized {
+    return {} as RouterLocationNormalized
+  }
+
+  /**
+   * Transforms a RouterLocation object into a URL string. If a string is
+   * passed, it returns the string itself
+   * @param location RouterLocation to resolve to a url
+   */
+  resolve(location: Readonly<RouterLocation>): string {
+    if (typeof location === 'string') return location
+    if ('path' in location) {
+      // TODO: convert query, hash, warn params
+      return location.path
+    }
+
+    let matcher: RouteMatcher | void
+    if (!('name' in location)) {
+      // TODO: use current location
+      // location = {...location, name: this.}
+      matcher = this.routes.find(r => r.record.name === this.currentRoute.name)
+      // return '/using current location'
+    } else {
+      matcher = this.routes.find(r => r.record.name === location.name)
+    }
+
+    if (!matcher) {
+      // TODO: error
+      throw new Error('No match for' + location)
+    }
+
+    return matcher.resolve(location.params || {})
+  }
+}
index 1f356bc4987152ccdbf30016dcd7d382d8013b4e..3b609b9e01f17ce6e48febd72f2171016d360ae0 100644 (file)
@@ -6,7 +6,7 @@ export type ParamsType = Record<string, string | string[]>
 //   (params: ParamsType): any
 // }
 
-// export interface Location<PT extends PropsTransformer> {
+// export interface RouterLocation<PT extends PropsTransformer> {
 //   record: RouteRecord<PT>
 //   path: string
 //   params: ReturnType<PT>
@@ -23,8 +23,8 @@ export interface RouteRecord {
   // props: PT
 }
 
-// TODO location should be an object
-export type Location =
+// TODO: location should be an object
+export type RouterLocation =
   | string
   | {
       path: string
@@ -37,6 +37,14 @@ export type Location =
       params: ParamsType
     }
 
+export interface RouterLocationNormalized {
+  path: string
+  name?: string
+  params: ParamsType
+  query: TODO
+  hash: TODO
+}
+
 export type HistoryLocation = string
 
 // pushState clones the state passed and do not accept everything