matchParams('/home', '/', null)
})
+ it('allow a trailing slash', () => {
+ matchParams('/home', '/home/', {})
+ matchParams('/a/b', '/a/b/', {})
+ })
+
+ it('allow a trailing slash in repeated params', () => {
+ matchParams('/a/:id+', '/a/b/c/d/', { id: ['b', 'c', 'd'] })
+ matchParams('/a/:id*', '/a/b/c/d/', { id: ['b', 'c', 'd'] })
+ matchParams('/a/:id*', '/a/', { id: '' })
+ matchParams('/a/:id*', '/a', { id: '' })
+ })
+
+ it('allow no slash', () => {
+ matchParams('/home', '/home/', null, { strict: true })
+ matchParams('/home', '/home', {}, { strict: true })
+ })
+
it('is insensitive by default', () => {
matchParams('/home', '/HOMe', {})
})
const keys: ParamKey[] = []
for (const segment of segments) {
- pattern += '/'
+ if (!segment.length) pattern += '/'
- for (const token of segment) {
+ for (let tokenIndex = 0; tokenIndex < segment.length; tokenIndex++) {
+ const token = segment[tokenIndex]
if (token.type === TokenType.Static) {
+ // prepend the slash if we are starting a new segment
+ if (!tokenIndex) pattern += '/'
pattern += token.value
} else if (token.type === TokenType.Param) {
keys.push({
)
}
}
- pattern += token.repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`
- if (token.optional) pattern += '?'
+ // (?:\/((?:${re})(?:\/(?:${re}))*))
+ let subPattern = token.repeatable
+ ? `((?:${re})(?:/(?:${re}))*)`
+ : `(${re})`
+
+ if (!tokenIndex)
+ subPattern = token.optional ? `(?:/${subPattern})?` : '/' + subPattern
+ else subPattern += token.optional ? '?' : ''
+
+ pattern += subPattern
}
}
}
- pattern += options.end ? '$' : ''
+ // TODO: warn double trailing slash
+ if (!options.strict) pattern += '/?'
+
+ if (options.end) pattern += '$'
const re = new RegExp(pattern, options.sensitive ? '' : 'i')