Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Named capturing groups proposal #33

Merged
merged 2 commits into from
Apr 17, 2024
Merged

Named capturing groups proposal #33

merged 2 commits into from
Apr 17, 2024

Conversation

easing
Copy link
Contributor

@easing easing commented Apr 9, 2024

While fixing RegExp for optional params I got an idea and here is an example of how named capturing groups can be used for params detection. Not sure if it should be merged or not. In general I only want to highlight a possible direction of thinking for future improvements.

This PR

  • allow to define RegExp routes without callback
  • removes the neediness of callbacks for string patterns (identically closures was defined for each route previously)
  • provides a little bit cleaner way for params extraction from path (standard language feature used instead of fetch by index from extracted by regex parameters names array)
  • reduce size by 12 bytes

How named capturing works:

let path = "/profile/10/contacts"
let pattern = /\/profile\/(?<id>\d+)\/(?<tab>\w+)/

path.match(pattern)

[
  '/profile/10/contacts',
  '10',
  'contacts',
  index: 0,
  input: '/profile/10/contacts',
  groups: [Object: null prototype] { id: '10', tab: 'contacts' } // ← our desired params
]

Also, with named capturing groups it's possible to create links for regex routes. It's not bulletproof and production ready cause it’s impossible to handle all regex related features here, but can be used in simple cases when regex pattern contains only parameter value type checking like in example below.

function regexpRouteLink(regexp, params) {
  let link = regexp.source
    .replace(/\\\//g, '/')
    .replace(/^\^/, '')
    .replace(/\$$/, '')
	
  Object.entries(params).forEach(p => {
    link = link.replace(new RegExp(`(\\(\\?<${p[0]}>[^/]*\\))`), p[1])
  })

  return link;
}

let regexp = /^\/profile\/(?<id>\d+)\/(?<tab>\w+)$/i

regexpRouteLink(regexp, { id: 10, tab: 'contacts' }) // => /profile/10/contacts

@ai
Copy link
Member

ai commented Apr 9, 2024

I like the idea, but will be able to think about it only after finishing my talk.

I will return to it on another week.

@ai ai merged commit 6f3616c into nanostores:main Apr 17, 2024
3 checks passed
@ai
Copy link
Member

ai commented Apr 17, 2024

Thanks for the idea. It was released in 0.15.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants