]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat: encode route params
authorEduardo San Martin Morote <posva13@gmail.com>
Fri, 16 Aug 2019 15:53:04 +0000 (17:53 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Fri, 16 Aug 2019 15:53:04 +0000 (17:53 +0200)
__tests__/matcher.spec.js
explorations/html5.html
src/components/Link.ts
src/matcher.ts
src/router.ts

index 3b70f325a2425a1b10a0f186d9f5fdd89b3dfd43..7c6494ea18cb327c08a117aface48c8308e7fabc 100644 (file)
@@ -453,7 +453,6 @@ describe('Router Matcher', () => {
           assertRedirect(
             records,
             {
-              name: undefined,
               path: '/a/foo',
             },
             {
index 06914f085c98a0875f7cb8e4ee650f83a39f179e..2dd2944f7082b013380adec42da01f8c46548307 100644 (file)
         <li>
           <router-link to="/n/%E2%82%AC">/n/%E2%82%AC</router-link>
         </li>
+        <li>
+          <router-link :to="{ name: 'docs', params: { id: '€uro' }}"
+            >/docs/€uro (object)</router-link
+          >
+        </li>
         <li>
           <router-link to="/n/€">/n/€</router-link>
         </li>
index ed37322c5d14588c23e0b7daa4f61e65c9d4d9fa..fee83cf15471007365a0d5e95d231f1d335f0ebb 100644 (file)
@@ -25,7 +25,7 @@ const Link: Component = {
     let url: HistoryLocationNormalized
     let location: RouteLocationNormalized
     // TODO: refactor router code and use its function istead of having a copied version here
-    if (typeof to === 'string' || 'path' in to) {
+    if (typeof to === 'string' || ('path' in to && !('name' in to))) {
       url = history.utils.normalizeLocation(to)
       // TODO: should allow a non matching url to allow dynamic routing to work
       location = router.resolveLocation(url, from)
index aaa6ea9c865f5cf099ac93c0e5eeb3a018d7d715..8bcb291fc6026de642c91da7eb2bf337c0e27779 100644 (file)
@@ -330,7 +330,33 @@ export class RouterMatcher {
     let path: MatcherLocationNormalized['path']
     let name: MatcherLocationNormalized['name']
 
-    if ('path' in location) {
+    if ('name' in location && location.name) {
+      matcher = this.matchers.find(m => m.record.name === location.name)
+
+      if (!matcher) throw new NoRouteMatchError(currentLocation, location)
+
+      name = matcher.record.name
+      // TODO: merge params
+      params = location.params || currentLocation.params
+      // params are automatically encoded
+      // TODO: try catch to provide better error messages
+      path = matcher.resolve(params)
+      // TODO: check missing params
+
+      if ('redirect' in matcher.record) {
+        const { redirect } = matcher.record
+        return {
+          redirect,
+          normalizedLocation: {
+            name,
+            path,
+            matched: [],
+            params,
+            meta: matcher.record.meta || {},
+          },
+        }
+      }
+    } else if ('path' in location) {
       matcher = this.matchers.find(m => m.re.test(location.path))
 
       // TODO: if no matcher, return the location with an empty matched array
@@ -346,13 +372,26 @@ export class RouterMatcher {
       const result = matcher.re.exec(path)
 
       if (!result) {
+        // TODO: redo message: matching path against X
         throw new Error(`Error parsing path "${location.path}"`)
       }
 
       for (let i = 0; i < matcher.keys.length; i++) {
         const key = matcher.keys[i]
-        const value = result[i + 1]
+        let value: string = result[i + 1]
+        try {
+          value = decodeURIComponent(value)
+        } catch (err) {
+          if (err instanceof URIError) {
+            console.warn(
+              `[vue-router] failed decoding param "${key}" with value "${value}". When providing a string location or the "path" property, URL must be properly encoded (TODO: link). Falling back to unencoded value`
+            )
+          } else {
+            throw err
+          }
+        }
         if (!value) {
+          // TODO: handle optional params
           throw new Error(
             `Error parsing path "${location.path}" when looking for param "${key}"`
           )
@@ -360,30 +399,6 @@ export class RouterMatcher {
         params[key] = value
       }
 
-      if ('redirect' in matcher.record) {
-        const { redirect } = matcher.record
-        return {
-          redirect,
-          normalizedLocation: {
-            name,
-            path,
-            matched: [],
-            params,
-            meta: matcher.record.meta || {},
-          },
-        }
-      }
-      // named route
-    } else if ('name' in location) {
-      matcher = this.matchers.find(m => m.record.name === location.name)
-
-      if (!matcher) throw new NoRouteMatchError(currentLocation, location)
-
-      name = matcher.record.name
-      params = location.params || currentLocation.params // TODO: normalize params
-      path = matcher.resolve(params)
-      // TODO: check missing params
-
       if ('redirect' in matcher.record) {
         const { redirect } = matcher.record
         return {
index fa3781e7144b38617d0aefb49cdf1989c413469f..8480559d007c7e9c436e568ccb6e1ed753f63773 100644 (file)
@@ -225,7 +225,7 @@ export class Router {
     let url: HistoryLocationNormalized
     let location: RouteLocationNormalized
     // TODO: refactor into matchLocation to return location and url
-    if (typeof to === 'string' || 'path' in to) {
+    if (typeof to === 'string' || ('path' in to && !('name' in to))) {
       url = this.history.utils.normalizeLocation(to)
       // TODO: should allow a non matching url to allow dynamic routing to work
       location = this.resolveLocation(url, this.currentRoute)