Skip to content

Instantly share code, notes, and snippets.

@CodeWitchBella
Last active July 26, 2021 10:21
Show Gist options
  • Save CodeWitchBella/33613b34885df4ac3c404ebc3c12a823 to your computer and use it in GitHub Desktop.
Save CodeWitchBella/33613b34885df4ac3c404ebc3c12a823 to your computer and use it in GitHub Desktop.
Match Path

UPDATE: capture groups are supported in firefox since July 2020 (Firefox 78)

Firefox currently does not support capture groups https://bugzilla.mozilla.org/show_bug.cgi?id=1367105

But the non-capture group version is still better than https://bundlephobia.com/result?p=url-pattern@1.0.3

Example inputs and outputs:

matchPath('/hello/:world', '/hello/123') // { world: '123' }
matchPath('/hello/:world', '/hello/123/test') // { world: '123' }
matchPath('/hello/:world', '/abc') // {}

It could certainly be extented to allow exact matches (just add $ at the end of the regexp) but doing simple thing well without unneccessary features was exactly the point.

function matchPath(pattern: string, path: string) {
const segments = pattern
.split('/')
.filter(Boolean)
.map((segment) => (segment.startsWith(':') ? `(?<${segment.substring(1)}>[^/]+)` : segment))
return new RegExp(`^/?${segments.join('/')}`).exec(path)?.groups || {}
}
function matchPath(pattern: string, path: string) {
const groups: { [key: string]: number } = {}
let groupCounter = 1
const segments = pattern
.split('/')
.filter(Boolean)
.map((segment) => {
if (!segment.startsWith(':')) return segment
groups[segment.substring(1)] = groupCounter
groupCounter += 1
return '([^/]+)'
})
const match = path.match(new RegExp(`^/?${segments.join('/')}`))
if (!match) return {}
return Object.fromEntries(Object.entries(groups).map(([k, v]) => [k, match[v]]))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment