]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat: stringify url
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 11 Dec 2019 09:21:04 +0000 (10:21 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 18 Dec 2019 09:26:15 +0000 (10:26 +0100)
__tests__/matcher/path-parser.spec.ts
src/matcher/tokenizer.ts

index 866c6ce0f095e927faeac278a7cd0f75f38e2603..db412e3aa697e4eb307f220e5caab2f324610326 100644 (file)
@@ -422,6 +422,18 @@ describe('Path parser', () => {
       })
     })
 
+    it('catch all', () => {
+      matchParams('/:rest(.*)', '/a/b/c', { rest: 'a/b/c' })
+      matchParams('/:rest(.*)/no', '/a/b/c/no', { rest: 'a/b/c' })
+    })
+
+    it('catch all non-greedy', () => {
+      matchParams('/:rest(.*?)/b/:other(.*)', '/a/b/c', {
+        rest: 'a',
+        other: 'c',
+      })
+    })
+
     it('param multiple', () => {
       matchParams('/:a-:b-:c', '/one-two-three', {
         a: 'one',
@@ -450,4 +462,57 @@ describe('Path parser', () => {
 
     // end of parsing urls
   })
+
+  describe('generating urls', () => {
+    function matchStringify(
+      path: string,
+      params: Exclude<
+        ReturnType<ReturnType<typeof tokensToParser>['parse']>,
+        null
+      >,
+      expectedUrl: string
+    ) {
+      const pathParser = tokensToParser(tokenizePath(path))
+
+      expect(pathParser.stringify(params)).toEqual(expectedUrl)
+    }
+
+    it('no params one segment', () => {
+      matchStringify('/home', {}, '/home')
+    })
+
+    it('single param one segment', () => {
+      matchStringify('/:id', { id: 'one' }, '/one')
+    })
+
+    it('multiple param one segment', () => {
+      matchStringify('/:a-:b', { a: 'one', b: 'two' }, '/one-two')
+    })
+
+    it('repeatable params+', () => {
+      matchStringify('/:a+', { a: ['one', 'two'] }, '/one/two')
+    })
+
+    it('repeatable params*', () => {
+      matchStringify('/:a*', { a: ['one', 'two'] }, '/one/two')
+    })
+
+    it('optional param?', () => {
+      matchStringify('/:a?/other', { a: '' }, '/other')
+      matchStringify('/:a?/other', {}, '/other')
+    })
+
+    it('optional param? with static segment', () => {
+      matchStringify('/b-:a?/other', { a: '' }, '/b-/other')
+      matchStringify('/b-:a?/other', {}, '/b-/other')
+    })
+
+    it('optional param*', () => {
+      matchStringify('/:a*/other', { a: '' }, '/other')
+      matchStringify('/:a*/other', { a: [] }, '/other')
+      matchStringify('/:a*/other', {}, '/other')
+    })
+
+    // end of stringifying urls
+  })
 })
index d5fba2f4dfadc8a6584060d7d8b113f2dc8e01da..5c4ff57948dc6e0120ae4c8e299a46cd758e07f2 100644 (file)
@@ -245,7 +245,32 @@ export function tokensToParser(segments: Array<Token[]>): PathParser {
 
   function stringify(params: Params): string {
     let path = ''
-    // TODO: implem
+    let avoidDuplicatedSlash = false
+    for (const segment of segments) {
+      if (!avoidDuplicatedSlash || path[path.length - 1] !== '/') path += '/'
+      avoidDuplicatedSlash = false
+
+      for (const token of segment) {
+        const { value } = token
+        if (token.type === TokenType.Static) {
+          path += value
+        } else if (token.type === TokenType.Param) {
+          const param: string | string[] = value in params ? params[value] : ''
+
+          if (Array.isArray(param) && !token.repeatable)
+            throw new Error(
+              `Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`
+            )
+          const text: string = Array.isArray(param) ? param.join('/') : param
+          if (!text) {
+            if (!token.optional)
+              throw new Error(`Missing required param "${value}"`)
+            else avoidDuplicatedSlash = true
+          }
+          path += text
+        }
+      }
+    }
 
     return path
   }