]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
refactor(parser): using local variables
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 16 Dec 2019 08:33:42 +0000 (09:33 +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 15e3387ce712e4188f25bb6c9e98775d6b4d3acc..2afdb68245dc566b84fe42f7ada7af4cfab5cc0b 100644 (file)
@@ -28,6 +28,21 @@ describe('Path parser', () => {
       ])
     })
 
+    it.skip('groups', () => {
+      expect(tokenizePath('/one{-b_:id}')).toEqual([
+        [
+          { type: TokenType.Static, value: 'one' },
+          {
+            type: TokenType.Group,
+            groups: [
+              { type: TokenType.Static, value: '-b_' },
+              { type: TokenType.Param, value: 'id' },
+            ],
+          },
+        ],
+      ])
+    })
+
     // TODO: add test when groups exist
     it.skip('escapes } inside group', () => {
       expect(tokenizePath('/{\\{}')).toEqual([
index ac5ce4c354481699dd9ffe3e0e716a60f6931938..4988c5c6ba42e358cef923ddf0f852f63fa27c6d 100644 (file)
@@ -1,6 +1,7 @@
 export const enum TokenType {
   Static,
   Param,
+  Group,
 }
 
 const enum TokenizerState {
@@ -24,18 +25,23 @@ interface TokenParam {
   repeatable: boolean
 }
 
-type Token = TokenStatic | TokenParam
+interface TokenGroup {
+  type: TokenType.Group
+  value: Exclude<Token, TokenGroup>[]
+}
 
-// const ROOT_TOKEN: Token = {
-//   type: TokenType.Static,
-//   value: '/',
-// }
+type Token = TokenStatic | TokenParam | TokenGroup
+
+const ROOT_TOKEN: Token = {
+  type: TokenType.Static,
+  value: '',
+}
 
 const VALID_PARAM_RE = /[a-zA-Z0-9_]/
 
 export function tokenizePath(path: string): Array<Token[]> {
   if (!path) return [[]]
-  if (path === '/') return [[{ type: TokenType.Static, value: '' }]]
+  if (path === '/') return [[ROOT_TOKEN]]
   // remove the leading slash
   if (path[0] !== '/') throw new Error('A non-empty path must start with "/"')
 
@@ -119,6 +125,7 @@ export function tokenizePath(path: string): Array<Token[]> {
           state = TokenizerState.Param
         } else if (char === '{') {
           // TODO: handle group
+          addCharToBuffer()
         } else {
           addCharToBuffer()
         }
@@ -290,7 +297,6 @@ export function tokensToParser(
     // allow an empty path to be different from slash
     // if (!segment.length) pattern += '/'
 
-    // TODO: add strict and sensitive
     let segmentScore = segment.length
       ? segment.length > 1
         ? PathScore.SubSegment
@@ -308,36 +314,35 @@ export function tokensToParser(
 
         segmentScore += PathScore.Static
       } else if (token.type === TokenType.Param) {
+        const { value, repeatable, optional, regexp } = token
         keys.push({
-          name: token.value,
-          repeatable: token.repeatable,
-          optional: token.optional,
+          name: value,
+          repeatable: repeatable,
+          optional: optional,
         })
-        const re = token.regexp ? token.regexp : BASE_PARAM_PATTERN
+        const re = regexp ? regexp : BASE_PARAM_PATTERN
         if (re !== BASE_PARAM_PATTERN) {
           segmentScore += PathScore.BonusCustomRegExp
           try {
             new RegExp(`(${re})`)
           } catch (err) {
             throw new Error(
-              `Invalid custom RegExp for param "${token.value}": ` + err.message
+              `Invalid custom RegExp for param "${value}": ` + err.message
             )
           }
         }
         // (?:\/((?:${re})(?:\/(?:${re}))*))
-        let subPattern = token.repeatable
-          ? `((?:${re})(?:/(?:${re}))*)`
-          : `(${re})`
+        let subPattern = repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`
 
         if (!tokenIndex)
-          subPattern = token.optional ? `(?:/${subPattern})?` : '/' + subPattern
-        else subPattern += token.optional ? '?' : ''
+          subPattern = optional ? `(?:/${subPattern})?` : '/' + subPattern
+        else subPattern += optional ? '?' : ''
 
         pattern += subPattern
 
         segmentScore += PathScore.Dynamic
-        if (token.optional) segmentScore += PathScore.BonusOptional
-        if (token.repeatable) segmentScore += PathScore.BonusRepeatable
+        if (optional) segmentScore += PathScore.BonusOptional
+        if (repeatable) segmentScore += PathScore.BonusRepeatable
         if (re === '.*') segmentScore += PathScore.BonusWildcard
       }
     }
@@ -378,20 +383,19 @@ export function tokensToParser(
       avoidDuplicatedSlash = false
 
       for (const token of segment) {
-        const { value } = token
         if (token.type === TokenType.Static) {
-          path += value
+          path += token.value
         } else if (token.type === TokenType.Param) {
+          const { value, repeatable, optional } = token
           const param: string | string[] = value in params ? params[value] : ''
 
-          if (Array.isArray(param) && !token.repeatable)
+          if (Array.isArray(param) && !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}"`)
+            if (!optional) throw new Error(`Missing required param "${value}"`)
             else avoidDuplicatedSlash = true
           }
           path += text