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

consider generating URL strings from a URLPattern #73

Open
wanderview opened this issue Aug 11, 2021 · 8 comments
Open

consider generating URL strings from a URLPattern #73

wanderview opened this issue Aug 11, 2021 · 8 comments
Labels
addition/proposal New features or enhancements

Comments

@wanderview
Copy link
Member

One of the most frequent pieces of feedback we have gotten is that developers would like to generate URL and component strings from a URLPattern. For example, something like:

const pattern = new URLPattern({ pathname: '/product/:id' });
const my_pathname = pattern.generate('pathname', { id: '12345' });
// my_pathname is "/product/12345"

There is a discussions thread about this in #41. I'm filing this issue to consider as a future enhancement.

@Jamesernator
Copy link

Jamesernator commented Aug 14, 2021

The reference library does have some behaviour we would probably want to smooth other, especially given people are likely to use this for user input.

In particular path segments should probably be always validated and encoded by default, i.e. no attacks using slashes or relative path segments (./..).

Also path-to-regexp docs don't specify any behaviour for non-named pattern segments, e.g. what would we do with new URLPattern("/*.jpg"), one option would be to just throw an error, alternatively they could be treated as numeric-indexed, although this is tricky in itself e.g.:

const pattern = new URLPattern(`/foo/*`);
// Almost certainly "/foo/test" is the right behaviour here, as there's only
// a single pattern perhaps the array wrapper could be optional too
pattern.generate("pathname", ["test"]);

const pattern2 = new URLPattern("/images/*.jpg");
// Less clear as to which of these would be correct, it would make sense that people
// would want to include the full name, although others might expect that only the * is replaced
pattern2.generate("pathname", ["1.jpg"]);
pattern2.generate("pathname", ["1"]);

It might also make more sense as a separate API as with path-to-regexp, especially if not all syntax is supported for the reason above. i.e. new URLTemplate("/product/:id").generate("pathname", { id: "12345" })

@kettanaito
Copy link

kettanaito commented Aug 26, 2021

If you translate wildcard to a capturing group, the expectation should be that only that group is being replaced during compilation:

const pattern = new URLPattern("/images/*.jpg");
pattern.generate('pathname', ['1']) // "images/1.jpg"

I'd treat wildcards as non-named pattern segments, implying that the way they are compiled is the same as for the named segments. The only difference is the compilation input:

// This is a named equivalent of the wildcard example above.
const pattern = new URLPattern("/images/:filename.jpg");
pattern.generate('pathname', { filename: "1" }) // "images/1.jpg"

Replacing a fixed portion of the pattern (".jpg") would be unexpected.

@wanderview
Copy link
Member Author

Wildcards are unnamed matching groups today. So they do indeed get an automatically assigned numeric name.

@kettanaito
Copy link

kettanaito commented Aug 26, 2021

I was mainly addressing the comment from @Jamesernator in regards to the ambiguous match of *.jpg. I think the expectation is to have only the asterisk replaced, just as the expectation is that only a named parameter is replaced (:name.jpg). I think this may not be a concern.

@Haroenv
Copy link

Haroenv commented Sep 2, 2021

Just would like to chime in that this is very important, and that I can’t imagine a case where you read urls into objects without also turning objects into urls. Search pages for example have lots of generated links (think filters, pagination), but also read the url into local state.

@jimmywarting
Copy link

jimmywarting commented Feb 3, 2022

I were just merely considering if a result could be mutable...
for example: Say that you are on shopify.com/categories/computers and want to navigate to games section shopify.com/categories/games

const pattern = new URLPattern({ pathname: ':vendor/categories/:category' })
// Get current url pattern
const result = pattern.exec(location.href)

result.pathname.groups.category = 'games' // Modify current url match result
location.href = result.toString() // change the url location

Thinking this could be useful for a adv search with 2 way data binding or something.

all doe a generate function could work as equally good, maybe mutable url pattern result isn't desirable?

@Haroenv
Copy link

Haroenv commented Feb 3, 2022

the pattern being mutable can make sense, as new URL is a precedence, but personally I would need to make a copy of the pattern for every change then, as you have many links with different state, as it's not the current state you want to show in the URL, but a possible future state

@guy-borderless
Copy link

Would be helpful for my use case. I use a URL pattern to

  1. determine type of page
  2. extract information from the url
  3. reconstruct the URL from extracted information

I'm sure this will be a common enough use case for URLPattern

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements
Development

No branches or pull requests

7 participants