From: Eduardo San Martin Morote Date: Fri, 16 Aug 2019 15:53:04 +0000 (+0200) Subject: feat: encode route params X-Git-Tag: v4.0.0-alpha.0~269 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9d080c35dbd10bc5b6b259a5a1c60e7a78948b33;p=thirdparty%2Fvuejs%2Frouter.git feat: encode route params --- diff --git a/__tests__/matcher.spec.js b/__tests__/matcher.spec.js index 3b70f325..7c6494ea 100644 --- a/__tests__/matcher.spec.js +++ b/__tests__/matcher.spec.js @@ -453,7 +453,6 @@ describe('Router Matcher', () => { assertRedirect( records, { - name: undefined, path: '/a/foo', }, { diff --git a/explorations/html5.html b/explorations/html5.html index 06914f08..2dd2944f 100644 --- a/explorations/html5.html +++ b/explorations/html5.html @@ -47,6 +47,11 @@
  • /n/%E2%82%AC
  • +
  • + /docs/€uro (object) +
  • /n/€
  • diff --git a/src/components/Link.ts b/src/components/Link.ts index ed37322c..fee83cf1 100644 --- a/src/components/Link.ts +++ b/src/components/Link.ts @@ -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) diff --git a/src/matcher.ts b/src/matcher.ts index aaa6ea9c..8bcb291f 100644 --- a/src/matcher.ts +++ b/src/matcher.ts @@ -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 { diff --git a/src/router.ts b/src/router.ts index fa3781e7..8480559d 100644 --- a/src/router.ts +++ b/src/router.ts @@ -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)