]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix: handle subsegments
authorEduardo San Martin Morote <posva13@gmail.com>
Fri, 15 Aug 2025 12:29:38 +0000 (14:29 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Fri, 15 Aug 2025 12:29:38 +0000 (14:29 +0200)
packages/router/src/experimental/route-resolver/matchers/matcher-pattern.spec.ts
packages/router/src/experimental/route-resolver/matchers/matcher-pattern.ts

index 0a4c8b04e03a97be30421e33e2b8fac930260b63..6381c13cda8296e637bab053f7331290972117b9 100644 (file)
@@ -217,4 +217,26 @@ describe('MatcherPatternPathCustom', () => {
       '/teams/123/456'
     )
   })
+
+  it('sub segments (params + static)', () => {
+    const pattern = new MatcherPatternPathCustomParams(
+      /^\/teams\/([^/]+?)-b-([^/]+?)$/i,
+      {
+        teamId: {},
+        otherId: {},
+      },
+      ['teams', [0, '-b-', 0]]
+    )
+
+    expect(pattern.match('/teams/123-b-456')).toEqual({
+      teamId: '123',
+      otherId: '456',
+    })
+    expect(() => pattern.match('/teams/123-b')).toThrow()
+    expect(() => pattern.match('/teams/123-b-456/c')).toThrow()
+    expect(() => pattern.match('/teams/')).toThrow()
+    expect(pattern.build({ teamId: '123', otherId: '456' })).toBe(
+      '/teams/123-b-456'
+    )
+  })
 })
index eb38aad5df16277c8df9d13d905e5835e7eb80cb..d16a51ae8120de4ce33e560e6a0e13be050ad33b 100644 (file)
@@ -291,7 +291,7 @@ export class MatcherPatternPathCustomParams<
     // A better version could be using all the parts to join them
     // .e.g ['users', 0, 'profile', 1] -> /users/123/profile/456
     // numbers are indexes of the params in the params object keys
-    readonly pathParts: Array<string | number>
+    readonly pathParts: Array<string | number | Array<string | number>>
   ) {
     this.paramsKeys = Object.keys(this.params) as Array<keyof TParamsOptions>
   }
@@ -335,16 +335,35 @@ export class MatcherPatternPathCustomParams<
         .map(part => {
           if (typeof part === 'string') {
             return part
+          } else if (typeof part === 'number') {
+            const paramName = this.paramsKeys[paramIndex++]
+            const paramOptions = this.params[paramName]
+            const value: ReturnType<NonNullable<ParamParser['set']>> = (
+              paramOptions.set || identityFn
+            )(params[paramName])
+
+            return Array.isArray(value)
+              ? value.map(encodeParam).join('/')
+              : encodeParam(value)
+          } else {
+            return part
+              .map(subPart => {
+                if (typeof subPart === 'string') {
+                  return subPart
+                }
+
+                const paramName = this.paramsKeys[paramIndex++]
+                const paramOptions = this.params[paramName]
+                const value: ReturnType<NonNullable<ParamParser['set']>> = (
+                  paramOptions.set || identityFn
+                )(params[paramName])
+
+                return Array.isArray(value)
+                  ? value.map(encodeParam).join('/')
+                  : encodeParam(value)
+              })
+              .join('')
           }
-          const paramName = this.paramsKeys[paramIndex++]
-          const paramOptions = this.params[paramName]
-          const value: ReturnType<NonNullable<ParamParser['set']>> = (
-            paramOptions.set || identityFn
-          )(params[paramName])
-
-          return Array.isArray(value)
-            ? value.map(encodeParam).join('/')
-            : encodeParam(value)
         })
         .filter(identityFn) // filter out empty values
         .join('/')