]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
add more code
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 7 Feb 2019 19:20:49 +0000 (20:20 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 7 Feb 2019 19:20:49 +0000 (20:20 +0100)
src/history/base.ts
src/history/html5.ts
src/index.ts
src/types/index.ts
tsconfig.json

index 7cd5ae61a4d4eed52a66739f73d1be8b776b4588..8633930ac70c2322f555d752f5bf393e895bc821 100644 (file)
@@ -1,13 +1,20 @@
-import { START, Location } from '../types/index'
+import { START, HistoryLocation } from '../types/index'
 export interface NavigationCallback {
-  (location: string): void
+  (to: HistoryLocation, from: HistoryLocation): void
 }
 
 export default abstract class BaseHistory {
   // previousState: object
-  location: Location
-  abstract push(to: Location): void
+  location: HistoryLocation
+  abstract push(to: HistoryLocation): void
+  abstract replace(to: HistoryLocation): void
   abstract listen(callback: NavigationCallback): Function
+  /**
+   * ensure the current location using the external source
+   * for example, in HTML5 and hash history, that would be
+   * location.pathname
+   */
+  abstract ensureLocation(): void
 
   constructor() {
     this.location = START
index edf0b317469937bcd4229a16472df806e5c219e6..ccd63e68ed343fa269295d11e472edb71d416eaf 100644 (file)
@@ -1,26 +1,52 @@
 import BaseHistory, { NavigationCallback } from './base'
-import { Location } from '../types/index'
+import { HistoryLocation } from '../types/index'
 
 export default class HTML5History extends BaseHistory {
-  history: typeof window.history
+  private history = window.history
   constructor() {
     super()
-    this.history = window.history
   }
 
-  push(to: Location): void {
-    // TODO resolve url
-    this.history.pushState(
+  ensureLocation() {
+    const to = window.location.pathname
+    this.replace(to)
+  }
+
+  replace(to: HistoryLocation) {
+    if (to === this.location) return
+    this.history.replaceState(
       {
-        from: this.location,
+        ...(this.history.state || {}),
         to,
       },
       '',
       to
     )
+    this.location = to
+  }
+
+  push(to: HistoryLocation) {
+    // TODO resolve url
+    // TODO compare current location to prevent navigation
+    if (to === this.location) return
+    const state = {
+      from: this.location,
+      to,
+    }
+    console.log('push', state)
+    this.history.pushState(state, '', to)
+    this.location = to
   }
 
   listen(callback: NavigationCallback): Function {
+    window.addEventListener('popstate', ({ state }) => {
+      const from = this.location
+      // we have the state from the old entry, not the current one being removed
+      // TODO correctly parse pathname
+      this.location = state ? state.to : window.location.pathname
+      callback(this.location, from)
+    })
+
     return () => {}
   }
 }
index 8de295dbc67e214719eaf0955db1b23ed4019c80..14b7c8b24c0ea03a4cfd6df7843159ae63fb64fb 100644 (file)
@@ -1 +1,71 @@
-class Router {}
+import BaseHistory from './history/base'
+import pathToRegexp from 'path-to-regexp'
+import { Location, RouteRecord } from './types/index'
+
+interface RouterOptions {
+  history: BaseHistory
+  routes: RouteRecord[]
+}
+
+interface RouteMatcher {
+  re: RegExp
+  record: RouteRecord
+  keys: string[]
+}
+
+export class Router {
+  protected history: BaseHistory
+  private routes: RouteMatcher[]
+
+  constructor(options: RouterOptions) {
+    this.history = options.history
+    this.history.ensureLocation()
+
+    this.routes = options.routes.map(record => {
+      const keys: pathToRegexp.Key[] = []
+      // TODO: if children use option end: false ?
+      const re = pathToRegexp(record.path, keys)
+      return { re, keys: keys.map(k => '' + k.name), record }
+    })
+  }
+
+  /**
+   * Trigger a navigation, should resolve all guards first
+   * @param to Where to go
+   */
+  push(to: Location) {
+    // TODO: resolve URL
+    const path = this.resolve(to)
+    // TODO: call hooks, guards
+    this.history.push(path)
+  }
+
+  getRouteRecord(location: Location) {}
+
+  /**
+   * Transforms a Location object into a URL string. If a string is
+   * passed, it returns the string itself
+   * @param location Location to resolve to a url
+   */
+  resolve(location: Location): string {
+    if (typeof location === 'string') return location
+    if ('path' in location) {
+      // TODO: convert query, hash, warn params
+      return location.path
+    }
+
+    if (!('name' in location)) {
+      // TODO: use current location
+      // location = {...location, name: this.}
+      return '/heeey'
+    }
+    const matcher = this.routes.find(r => r.record.name === location.name)
+    if (!matcher) {
+      // TODO: error
+      throw new Error('No match for' + location)
+    }
+    matcher.re
+    return '/TODO'
+    // this.matcher.match(location)
+  }
+}
index 43760487ca05d6c76dbae7f4f40218803f2f4342..39a941944c30ad571917d95379f2b354e83e13c5 100644 (file)
@@ -1,10 +1,10 @@
 type TODO = any
 
-type ParamsType = Record<string, string | string[]>
+export type ParamsType = Record<string, string | string[]>
 
-interface PropsTransformer {
-  (params: ParamsType): any
-}
+// interface PropsTransformer {
+//   (params: ParamsType): any
+// }
 
 // export interface Location<PT extends PropsTransformer> {
 //   record: RouteRecord<PT>
@@ -16,14 +16,23 @@ interface PropsTransformer {
 // since in callbacks we don't know where we are coming from
 // and I don't thin it's possible to filter out the route
 // by any means
-export interface RouteRecord<PT extends PropsTransformer> {
+export interface RouteRecord {
   path: string | RegExp
   component: TODO
-  name: string
-  props: PT
+  name?: string
+  // props: PT
 }
 
 // TODO location should be an object
-export type Location = string
+export type Location =
+  | string
+  | {
+      path: string
+    }
+  | {
+      name: string
+      params?: Record<string, string>
+    }
+export type HistoryLocation = string
 
-export const START: Location = ''
+export const START: HistoryLocation = '/'
index 6d385490fecd7f935bcf56cad38134c24a0811e8..b84769fc994c4dcaa64f4a8c415c8b97fbb3603c 100644 (file)
@@ -10,7 +10,7 @@
     // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
     // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
     // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
-    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
+    "sourceMap": true /* Generates corresponding '.map' file. */,
     // "outFile": "./",                       /* Concatenate and emit output to single file. */
     "outDir": "./dist" /* Redirect output structure to the directory. */,
     // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */