]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
more matching
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 4 Apr 2019 17:37:44 +0000 (19:37 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 4 Apr 2019 17:37:44 +0000 (19:37 +0200)
explorations/html5.ts
src/history/base.ts
src/history/html5.ts
src/index.ts
src/matcher.ts
src/types/index.ts

index dff41b04e71baeb7df16bbea4f04e17e6adcddb5..fa922ca68b839c1dccbcac4f59c206e061e7cace 100644 (file)
@@ -55,6 +55,6 @@ r.push({
   },
 })
 
-r.push({
-  hash: '#hey',
-})
+// r.push({
+//   hash: '#hey',
+// })
index 35833b0e115fc0bff3d5248560660bc59f1739ad..763d936fcbbc1d0879a181e92038976490b8ad95 100644 (file)
@@ -3,6 +3,7 @@ import {
   HistoryLocation,
   NavigationCallback,
   RemoveListener,
+  HistoryURL,
 } from '../types/index'
 
 export default abstract class BaseHistory {
@@ -33,6 +34,13 @@ export default abstract class BaseHistory {
    */
   abstract listen(callback: NavigationCallback): RemoveListener
 
+  /**
+   * Transforms a URL into an object
+   * @param location location to normalize
+   * @param currentLocation current location, to reuse params and location
+   */
+  abstract parseURL(location: HistoryLocation): HistoryURL
+
   /**
    * ensure the current location matches the external source
    * For example, in HTML5 and hash history, that would be
index c549532e0dd08083a88a1af997f6884868524133..7134646c45ae1284c4a21e5c600215d4aff56eb0 100644 (file)
@@ -5,6 +5,7 @@ import {
   NavigationCallback,
   HistoryState,
   NavigationType,
+  HistoryURL,
 } from '../types/index'
 
 const cs = consola.withTag('html5')
@@ -116,6 +117,45 @@ export default class HTML5History extends BaseHistory {
     return teardown
   }
 
+  parseURL(location: string): HistoryURL {
+    let path = '',
+      search: HistoryURL['search'] = {},
+      searchString = '',
+      hash = ''
+
+    // Could use URL and URLSearchParams but IE 11 doesn't support it
+    const searchPos = location.indexOf('?')
+    const hashPos = location.indexOf(location, searchPos > -1 ? searchPos : 0)
+    if (searchPos > -1) {
+      path = location.slice(0, searchPos)
+      searchString = location.slice(
+        searchPos + 1,
+        hashPos > -1 ? hashPos : location.length - 1
+      )
+
+      // TODO: properly do this in a util function
+      search = searchString.split('&').reduce((search, entry) => {
+        const [key, value] = entry.split('=')
+        search[key] = value
+        return search
+      }, search)
+    }
+
+    if (hashPos > -1) {
+      path = path || location.slice(0, hashPos)
+      hash = location.slice(hashPos, location.length - 1)
+    }
+
+    path = path || location
+
+    return {
+      path,
+      // TODO: transform searchString
+      search,
+      hash,
+    }
+  }
+
   destroy() {
     for (const teardown of this._teardowns) teardown()
     this._teardowns = []
index 2df393680bd89d6369a3d395d23d70992acd7057..61adf9065dd4a3feb23d5af3072e5314c3e91a24 100644 (file)
@@ -30,9 +30,10 @@ export class Router {
    */
   push(to: RouterLocation) {
     // TODO: resolve URL
-    const path = this.matcher.resolve(to, this.currentRoute)
+    const location = this.matcher.resolve(to, this.currentRoute)
     // TODO: call hooks, guards
-    this.history.push(path)
+    this.history.push(location.fullPath)
+    this.currentRoute = location
   }
 
   getRouteRecord(location: RouterLocation) {}
index a47ac7ede560693caf88e212f50182ba02ddd3a7..fbb364682b38a7525e9953a125e26e11928179f1 100644 (file)
@@ -34,18 +34,6 @@ export class RouterMatcher {
     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
@@ -53,15 +41,31 @@ export class RouterMatcher {
    */
   resolve(
     location: Readonly<RouterLocation>,
-    currentLocation: RouterLocationNormalized
-  ): string {
-    if (typeof location === 'string') return location
+    currentLocation: Readonly<RouterLocationNormalized>
+  ): RouterLocationNormalized {
+    if (typeof location === 'string')
+      return {
+        path: location,
+        fullPath: location,
+        // TODO: resolve params, query and hash
+        params: {},
+        query: {},
+        hash: '',
+      }
 
     if ('path' in location) {
       // TODO: warn missing params
-      return (
-        location.path + stringifyQuery(location.query) + (location.hash || '')
-      )
+      // TODO: extract query and hash? warn about presence
+      return {
+        path: location.path,
+        query: location.query || {},
+        hash: location.hash || '',
+        params: {},
+        fullPath:
+          location.path +
+          stringifyQuery(location.query) +
+          (location.hash || ''),
+      }
     }
 
     let matcher: RouteMatcher | void
@@ -74,9 +78,7 @@ export class RouterMatcher {
           m => m.record.name === currentLocation.name
         )
       } else {
-        matcher = this.matchers.find(
-          m => m.record.path === currentLocation.path
-        )
+        matcher = this.matchers.find(m => m.re.test(currentLocation.path))
       }
       // return '/using current location'
     } else {
@@ -85,9 +87,19 @@ export class RouterMatcher {
 
     if (!matcher) {
       // TODO: error
-      throw new Error('No match for' + location)
+      throw new Error(
+        'No match for' + JSON.stringify({ ...currentLocation, ...location })
+      )
     }
 
-    return matcher.resolve(location.params || {})
+    // TODO: try catch to show missing params
+    const fullPath = matcher.resolve(location.params || {})
+    return {
+      path: fullPath, // TODO: extract path path, query, hash
+      fullPath,
+      query: {},
+      params: {},
+      hash: '',
+    }
   }
 }
index 9a0cc59cbfeca111dad3876b3300a0ca0f0cfb78..ea5c807059447249ce503a66be7dc346add14b42 100644 (file)
@@ -46,13 +46,19 @@ export type RouterLocation =
 
 export interface RouterLocationNormalized {
   path: string
+  fullPath: string
   name?: string
   params: RouteParams
   query: TODO
-  hash: TODO
+  hash: string
 }
 
 export type HistoryLocation = string
+export interface HistoryURL {
+  path: string
+  search: Record<string, string>
+  hash: string
+}
 
 // pushState clones the state passed and do not accept everything
 // it doesn't accept symbols, nor functions. It also ignores Symbols as keys
@@ -81,6 +87,7 @@ export const START_LOCATION_NORMALIZED: RouterLocationNormalized = {
   params: {},
   query: {},
   hash: '',
+  fullPath: '/',
 }
 
 export enum NavigationType {