expect(expectedRe).toBe(
pathParser.re
.toString()
- .replace(/(:?^\/|\/$)/g, '')
+ .replace(/(:?^\/|\/\w*$)/g, '')
.replace(/\\\//g, '/')
)
}
function matchParams(
path: string,
pathToTest: string,
- params: ReturnType<ReturnType<typeof tokensToParser>['parse']>
+ params: ReturnType<ReturnType<typeof tokensToParser>['parse']>,
+ options?: Parameters<typeof tokensToParser>[1]
) {
- const pathParser = tokensToParser(tokenizePath(path))
+ const pathParser = tokensToParser(tokenizePath(path), options)
expect(pathParser.parse(pathToTest)).toEqual(params)
}
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', {})
})
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<PathParserOptions> = {
+ 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<Token[]>): PathParser {
+export function tokensToParser(
+ segments: Array<Token[]>,
+ 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) {
}
}
- 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)