nuqs: Add a nice-url option that does not encode `/`, objects and arrays
Right now, all URLs are encoded in a way that make all “non-trivial” characters and arrays and objects look long, complex and quite frankly ugly.
It would be great to have the option opt out of the full and automatic encoding. Which also means the developer is responsible to make sure the URL does not have any problematic characters.
Config example from sindresorhus/query-string
: This library has an option to set encode:false
.
I used this in a previous project (more…)
Example of how it looks right now: /regionen/trto?map=10.6%2F53.6774%2F13.267&config=%21%28i~fromTo~a~~topics~…
I would like the map
to look as nice as on OSM https://www.openstreetmap.org/#map=10/53.6774/13.2670 for example 😃.
Example of our previous URL…
Our previous URL was not pretty either, but still al lot nicer to look but especially shorter at then the encoded version: https://radverkehrsatlas.de/regionen/trto?lat=53.6774&lng=13.267&zoom=10.6&theme=fromTo&bg=default&config=!(i~fromTo~topics~!(i~shops~s~!(i~hidden~a~_F)(i~default~a))(i~education~s~!(i~hidden~a)(i~default~a~_F))(i~places~s~!(i~hidden~a~_F)(i~default~a)(i~circle~a~_F))(i~buildings~s~!(i~hidden~a)(i~default~a~_F))(i~landuse~s~!(i~hidden~a~_F)(i~default~a))(i~barriers~s~!(i~hidden~a~_F)(i~default~a))(i~boundaries~s~!(i~hidden~a)(i~default~a~_F)(i~level-8~a~_F)(i~level-9-10~a~_F)))(i~bikelanes~topics~!(i~bikelanes~s~!(i~hidden~a~_F)(i~default~a)(i~verification~a~_F)(i~completeness~a~_F))(i~bikelanesPresence*_legacy~s~!(i~hidden~a)(i~default~a~_F))(i~places~s~!(i~hidden~a~_F)(i~default~a)(i~circle~a~_F))(i~landuse~s~!(i~hidden~a)(i~default~a~_F)))(i~roadClassification~topics~!(i~roadClassification*_legacy~s~!(i~hidden~a~_F)(i~default~a)(i~oneway~a~_F))(i~bikelanes~s~!(i~hidden~a)(i~default~a~_F)(i~verification~a~_F)(i~completeness~a~_F))(i~maxspeed*_legacy~s~!(i~hidden~a)(i~default~a~_F)(i~details~a~_F))(i~surfaceQuality*_legacy~s~!(i~hidden~a)(i~default~a~_F)(i~bad~a~_F)(i~completeness~a~_F)(i~freshness~a~_F))(i~places~s~!(i~hidden~a~_F)(i~default~a)(i~circle~a~_F))(i~landuse~s~!(i~hidden~a)(i~default~a~_F)))(i~lit~topics~!(i~lit*_legacy~s~!(i~hidden~a~_F)(i~default~a)(i~completeness~a~_F)(i~verification~a~_F)(i~freshness~a~_F))(i~places~s~!(i~hidden~a)(i~default~a~_F)(i~circle~a~_F))(i~landuse~s~!(i~hidden~a)(i~default~a~_F)))~
Current implementation: Reading https://github.com/47ng/next-usequerystate/discussions/343#discussioncomment-6985578 the encoding is done by calling URLSearchParams.toString
which encodes everything with encodeURIComponent
.
Possible solution: https://stackoverflow.com/questions/71316183/urlsearchparams-set-without-uriencoding show possible solutions to decode the URL before returning it either fully or in parts.
About this issue
- Original URL
- State: closed
- Created 9 months ago
- Reactions: 2
- Comments: 18 (13 by maintainers)
Commits related to this issue
- feat: Prettify URLs Don't URL-encode safe characters, and fix the array parser logic. Closes #355. — committed to 47ng/nuqs by franky47 8 months ago
- chore: Add practical test cases from #355 — committed to 47ng/nuqs by franky47 8 months ago
- Map: Make URLs look nice thanks to the newest next-usequerystate Thanks to https://github.com/47ng/next-usequerystate/issues/355 Closes https://github.com/FixMyBerlin/private-issues/issues/1060 — committed to FixMyBerlin/atlas-app by tordans 8 months ago
Giving this a try as I was porting shadcn/ui’s Tasks demo to
next-usequerystate
, and sorting options were indeed ugly.Here’s what we could do 🙃 (hint: maybe don’t.)
https://github.com/47ng/next-usequerystate/assets/1174092/d5a8c4eb-ffc4-4ac5-a2ff-728741f84177
I’ll try this on multiple browsers to see how they might accept non-encoded special characters and fine tune the query string renderer.
If a good set of defaults can be supported, I think we could avoid having an option for this and make it the default.
I’d say the easiest way to do this would be to implement a custom parser/serializer, that pre-encodes the string value as needed before returning it from the
serialize
method.I’ve published 1.9.0-beta.1 which includes test cases for your URLs, could you give it a try and see how far you can go before it breaks horribly? I have included the reasoning in PR #372 (a review would be most welcome).
Thanks @tordans! From my initial tests, it’s not just about encoding for pretty URL display in the browser, but more importantly to make sure copy-pasting a URL to share it with others won’t break the link by containing characters that may indicate the end of the URL, and drop the rest of the query string.
As an example, here’s the raw URL from above, unencoded:
https://example.com?exclamationMark=!&doubleQuote="&hash=%23&dollar=$&percent=%&ersand=%26&apostrophe='&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=<&equals==&greaterThan=>&questionMark=?&at=@&leftSquareBracket=[&backslash=&rightSquareBracket=]&caret=^&underscore=_&backtick=`&leftCurlyBrace={&pipe=|&rightCurlyBrace=}&tilde=~
GitHub seems to break at the
<
and>
characters. In contrast, VSCode’s builtin URL detection feature breaks earlier, at the"
,'
and backtick characters. Other platforms (eg: social networks, messengers) may have other URL-breaking characters.Chrome 117, macOS, https://www.whatsmybrowser.org/b/MO73G
https://example.com/?exclamationMark=!&doubleQuote=%22&hash=%23&dollar=$&percent=%&ersand=%26&apostrophe=%27&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=%3C&equals==&greaterThan=%3E&questionMark=?&at=@&leftSquareBracket=[&backslash=&rightSquareBracket=]&caret=^&underscore=_&backtick=`&leftCurlyBrace={&pipe=|&rightCurlyBrace=}&tilde=~
Safari 16, macOS, https://www.whatsmybrowser.org/b/20H86
https://example.com/?exclamationMark=!&doubleQuote=%22&hash=%23&dollar=$&percent=%&ersand=%26&apostrophe=%27&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=%3C&equals==&greaterThan=%3E&questionMark=?&at=@&leftSquareBracket=[&backslash=&rightSquareBracket=]&caret=^&underscore=_&backtick=`&leftCurlyBrace={&pipe=|&rightCurlyBrace=}&tilde=~
Firefox 118, macOS, https://www.whatsmybrowser.org/b/51WS3
https://example.com/?exclamationMark=!&doubleQuote=%22&hash=%23&dollar=$&percent=%&ersand=%26&apostrophe=%27&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=%3C&equals==&greaterThan=%3E&questionMark=?&at=@&leftSquareBracket=[&backslash=&rightSquareBracket=]&caret=^&underscore=_&backtick=`&leftCurlyBrace={&pipe=|&rightCurlyBrace=}&tilde=~
Safari 16, iOS, https://www.whatsmybrowser.org/b/40G5X
https://example.com/?exclamationMark=!&doubleQuote=%22&hash=%23&dollar=$&percent=%25&ersand=%26&apostrophe=%27&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=%3C&equals==&greaterThan=%3E&questionMark=?&at=@&leftSquareBracket=%5B&backslash=&rightSquareBracket=%5D&caret=%5E&underscore=_&backtick=%60&leftCurlyBrace=%7B&pipe=%7C&rightCurlyBrace=%7D&tilde=~
Chrome 118, iOS, https://www.whatsmybrowser.org/b/CTINA
https://example.com/?exclamationMark=!&doubleQuote=%22&hash=%23&dollar=$&percent=%25&ersand=%26&apostrophe=%27&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=%3C&equals==&greaterThan=%3E&questionMark=?&at=@&leftSquareBracket=%5B&backslash=&rightSquareBracket=%5D&caret=%5E&underscore=_&backtick=%60&leftCurlyBrace=%7B&pipe=%7C&rightCurlyBrace=%7D&tilde=~
Safari UIWebView 15 (Firefox Klar), macOS, https://www.whatsmybrowser.org/b/V5YGS
https://example.com?exclamationMark=!&doubleQuote="&hash=%23&dollar=$&percent=%&ersand=%26&apostrophe='&leftParenthesis=(&rightParenthesis=)&asterisk=*&plus=+&comma=,&hyphen=-&period=.&slash=/&colon=:&semicolon=;&lessThan=<&equals==&greaterThan=>&questionMark=?&at=@&leftSquareBracket=[&backslash=&rightSquareBracket=]&caret=^&underscore=_&backtick=`&leftCurlyBrace={&pipe=|&rightCurlyBrace=}&tilde=~
(Note: All macOS are copied in Workflowy first to transfer them in this issue, that might change thing again…)
I asked the LLMs to generate a URL that contains all non-alphanumerical printable ASCII characters to see which ones end up being encoded when displayed in the URL bar.
Could you please:
FYI, browsers on Linux would be much appreciated, thanks! 🙏
Edit: results so far: