molefrog / wouter

🥢 A minimalist-friendly ~2.1KB routing for React and Preact
https://npm.im/wouter
The Unlicense
6.41k stars 146 forks source link

Added support for regular expressions in paths #450

Closed JonahPlusPlus closed 1 month ago

JonahPlusPlus commented 1 month ago

This fixes #449.

By supporting regular expressions in paths, it becomes possible to lift validation out of routes and into the paths themselves.

What happens when you use a RegExp: The route doesn't run the parser, but just executes the regex. After executing the regex, instead of mapping the keys and values into an object, the indices of the regex result are mapped to an object and the named groups are assigned to the object as well.

For example:

// Route
/[/]([a-z]+)/
// Against "/foo", produces
{ 0: "foo" }

// Route
/[/](?<name>[a-z]+)/
// Against "/foo", produces
{ 0: "foo", name: "foo" }

Another thing to consider: should normal paths also expose params as indices? (so, should /:id become { 0: "foo", id: "foo" }, instead of just { id: "foo" }?)

stackblitz[bot] commented 1 month ago

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

codecov[bot] commented 1 month ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 100.00%. Comparing base (e106a9d) to head (44181fb).

Additional details and impacted files ```diff @@ Coverage Diff @@ ## v3 #450 +/- ## ========================================= Coverage 100.00% 100.00% ========================================= Files 1 1 Lines 1 1 ========================================= Hits 1 1 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

JonahPlusPlus commented 1 month ago

I changed it to handle the RegExp outside of the parser, so devs don't need to handle that case. With that, these changes aren't breaking (AFAIK; it's still a change to the public API).

molefrog commented 1 month ago

@JonahPlusPlus Hey, thank you! 👏 You've done an enormous work and everything seems good. I've looked briefly, so I'm going to take some time to understand better how it works.

JonahPlusPlus commented 1 month ago

Okay, so I got those changes done and I added one final change: string paths also return indices for the params as well as the keys.

So, matching "/:id" against /foo returns { 0: "foo", id: "foo" }. This is now consistent with regex paths. Keys override indices, so this should not be a breaking change for any library that uses number keys. (e.g. something that acts like "/:1/:0" won't break order)

Future work: Provide a way to optimize routes by caching string path regexes. Possible solution: allow passing { pattern, keys } objects to routes and allow for generating those objects outside of routes.


const idPath = cachePath("/:id");

<Route path={idPath}>
...
</Route>