From: Eduardo San Martin Morote Date: Thu, 12 Dec 2019 09:38:55 +0000 (+0100) Subject: feat(parser): add regexp options X-Git-Tag: v4.0.0-alpha.0~150 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ada09fafe4d4a48465a2b83e13c9bb5b5d365e77;p=thirdparty%2Fvuejs%2Frouter.git feat(parser): add regexp options --- diff --git a/__tests__/matcher/path-parser.spec.ts b/__tests__/matcher/path-parser.spec.ts index 28f7c8c4..ed4eabcc 100644 --- a/__tests__/matcher/path-parser.spec.ts +++ b/__tests__/matcher/path-parser.spec.ts @@ -328,7 +328,7 @@ describe('Path parser', () => { expect(expectedRe).toBe( pathParser.re .toString() - .replace(/(:?^\/|\/$)/g, '') + .replace(/(:?^\/|\/\w*$)/g, '') .replace(/\\\//g, '/') ) } @@ -430,9 +430,10 @@ describe('Path parser', () => { function matchParams( path: string, pathToTest: string, - params: ReturnType['parse']> + params: ReturnType['parse']>, + options?: Parameters[1] ) { - const pathParser = tokensToParser(tokenizePath(path)) + const pathParser = tokensToParser(tokenizePath(path), options) expect(pathParser.parse(pathToTest)).toEqual(params) } @@ -441,6 +442,25 @@ describe('Path parser', () => { matchParams('/home', '/', null) }) + it('is insensitive by default', () => { + matchParams('/home', '/HOMe', {}) + }) + + it('can be sensitive', () => { + matchParams('/home', '/HOMe', null, { sensitive: true }) + matchParams('/home', '/home', {}, { sensitive: true }) + }) + + it('can not match the beginning', () => { + matchParams('/home', '/other/home', null, { start: true }) + matchParams('/home', '/other/home', {}, { start: false }) + }) + + it('can not match the end', () => { + matchParams('/home', '/home/other', null, { end: true }) + matchParams('/home', '/home/other', {}, { end: false }) + }) + it('returns an empty object with no keys', () => { matchParams('/home', '/home', {}) }) diff --git a/src/matcher/tokenizer.ts b/src/matcher/tokenizer.ts index c6dc1291..3030b264 100644 --- a/src/matcher/tokenizer.ts +++ b/src/matcher/tokenizer.ts @@ -192,15 +192,60 @@ interface PathParser { stringify(params: Params): string } +interface PathParserOptions { + /** + * Makes the RegExp case sensitive. Defaults to false + */ + sensitive?: boolean + /** + * Should we allow a trailing slash. Defaults to true + */ + strict?: boolean + /** + * Should the RegExp match from the beginning by prepending a ^. Defaults to true + */ + start?: boolean + /** + * Should the RegExp match until the end by appending a $. Defaults to true + */ + end?: boolean + /** + * Encodes a static value. This is used to encode params for them to be valid on the URL + */ + encode?: (value: string) => string + /** + * Decodes a static value. This allows to produce decoded params when parsing an URL + */ + decode?: (value: string) => string +} + const BASE_PARAM_PATTERN = '[^/]+?' +const BASE_PATH_PARSER_OPTIONS: Required = { + sensitive: false, + strict: false, + start: true, + end: true, + // TODO: implement real ones + encode: v => v, + decode: v => v, +} + /** * TODO: add options strict, sensitive, encode, decode */ -export function tokensToParser(segments: Array): PathParser { +export function tokensToParser( + segments: Array, + extraOptions?: PathParserOptions +): PathParser { + const options = { + ...BASE_PATH_PARSER_OPTIONS, + ...extraOptions, + } + let score = 0 - let pattern = '^' + let pattern = options.start ? '^' : '' const keys: ParamKey[] = [] for (const segment of segments) { @@ -231,9 +276,9 @@ export function tokensToParser(segments: Array): PathParser { } } - pattern += '$' + pattern += options.end ? '$' : '' - const re = new RegExp(pattern) + const re = new RegExp(pattern, options.sensitive ? '' : 'i') function parse(path: string): Params | null { const match = path.match(re)