Ok, at long last, I think we have a solution for this that we could use without major rewrite.
It contains several methods: { url, urlComponent, urlBase, urlUnwrap }.
urlComponent is a template literal that escapes everything except already escaped components.
It returns a special class that is convertible to string.
urlUnwrap is a function that validates and unwraps instances of that class.
url is a template literal, that returns an URL instance with some additional checks.
Otherwise it escapes all components except already escaped by urlComponent.
As a special case, it allows the very first component to be an URL instance (aka base) and doesn't escape it then.
Simple usecase:
const arg = 'val/ue'
console.log(url`https://example.org/buz/${arg}`) // new URL(https://example.org/buz/val%2Fue')
const base = new URL('https://example.com/foo')
const arg = 'val/ue'
console.log(url`${base}/bar/${arg}`) // new URL('https://example.com/foo/bar/val%2Fue')
Note: it throws on '..' or when the result is an invalid URL.
Ok, at long last, I think we have a solution for this that we could use without major rewrite.
It contains several methods:
{ url, urlComponent, urlBase, urlUnwrap }
.urlComponent
is a template literal that escapes everything except already escaped components. It returns a special class that is convertible to string.urlUnwrap
is a function that validates and unwraps instances of that class.url
is a template literal, that returns anURL
instance with some additional checks. Otherwise it escapes all components except already escaped byurlComponent
. As a special case, it allows the very first component to be anURL
instance (aka base) and doesn't escape it then.Simple usecase:
Note: it throws on
'..'
or when the result is an invalid URL.E.g. this code:
Is (mostly, omitting extra safeguards) equivalent to:
Or
Or
Or
Or same with
fetchival
replaced by anything else as the last code sample doesn't rely on fetchival url concatenation anymore.Some extra checks are implemented, e.g. this code will throw:
While adding the missing
/
anywhere would work.