-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Path to regexp fix #11965
Path to regexp fix #11965
Conversation
🦋 Changeset detectedLatest commit: a06cfaa The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is blocked because it contains a minor
changeset. A reviewer will merge this at the next release if approved.
This is not enough, the template building in getRouteGenerator needs to be changed as |
Let me take a look at that and see! |
I updated the generator function. I tested it in several different scenarios and it seems to be working everywhere. |
@@ -31,7 +33,7 @@ export function getRouteGenerator( | |||
segment | |||
.map((part) => { | |||
if (part.spread) { | |||
return `:${part.content.slice(3)}(.*)?`; | |||
return `${part.content.slice(3)}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removes this part from being a parameter understood by path-to-regexp
to just being a literal, e.g. if the route was [...slug]
, previously this template literal created :slug(.*)
but after this change it just creates slug
. That’s probably why a lot of tests are failing.
We’ll need to check how to match the (.*)
behaviour in the latest version of path-to-regexp
(if possible).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From taking a look at the docs, it seems like this might be the way?
return `${part.content.slice(3)}`; | |
return `*${part.content.slice(3)}`; |
In a quick sandbox I spun up I ran this code:
const { compile } = require('path-to-regexp');
const toPath = compile('/*spread/:slug');
const path = toPath({ spread: ['one','two','three'], slug: 'four' });
console.log(path);
Which logged /one/two/three/four
as expected. We’d still need to see if it fully matches all behaviour specified in tests though or if there are edge cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this as well. It errors out and says "expected "slug" to be a non-empty array"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I guess currently we allow [...spread]
to match nothing (i.e. [...spread]
can match /
) and *spread
in path-to-regexp
doesn’t include support for an optional segment. They do mention {}
for optional segments, could try combining that with the wildcard?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then there is still the issue with the actual parameter value for rest (...) parameters, today it's "somedir/file.ext" and with the new version it should be ["somedir", "file.ext"], i.e. the parameter value needs to be split.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, when I did a quick investigation it looked like path-to-regexp
already expected an array in v6, so assumed that hadn’t changed, but I may have misunderstood.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I made some changes and im testing it all now to see.
Co-authored-by: Chris Swithinbank <[email protected]>
Sanitize parameters, preserve arrays for spread params like `slug`. Update type definitions and handle string-to-array conversion.
@@ -31,7 +37,7 @@ export function getRouteGenerator( | |||
segment | |||
.map((part) => { | |||
if (part.spread) { | |||
return `:${part.content.slice(3)}(.*)?`; | |||
return `*${part.content.slice(3)}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be
return `{*${part.content.slice(3)}}`;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or
return `*{${part.content.slice(3)}}`;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like none of those is working ...
return (params: Record<string, string[] | number | undefined>): string => { | ||
|
||
// Convert `slug` to an array if it's a string | ||
if (typeof params.slug === 'string') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The array conversion should only happen for parameters which RoutePart has spread set to true. And it should split the string if it contains a /.
Couple of things to try and help if someone is attempting this:
Set You might also find generating const path = new TokenData([
{ type: "text", value: "/" },
...segments.map(segment => {
if (part.spread) return { type: "wildcard", name: part.content }; // Wrap in `type: "group"` if you truly want it to be optional but that seems off to me, since it'd allow `//` with nothing in between?
if (part.dynamic) return { type: "param", name: part.content };
return { type: "text", value: part.content.normalize() }
});
]); |
I tried the update to and in the end think that what we used path-to-regexp for can be simply implemented without, see #11981. Maybe I overlooked some cases but all the tests are green locally. |
Good call, if you’re never using the template strings you don’t need the library. That’s basically what compile is doing already. |
That actually makes sense. I was planning on looking to see if we could do that. Glad to see it should be working. |
Superceded by #11983, thank you for contributing nonetheless! |
Changes
pnpm exec changeset
Testing
Docs