velt/net/url
A WHATWG-style URL and URLSearchParams, plus JS's URI encoding functions
(encodeURIComponent and the others): globals, as in Node; velt/net/url exports them too.
new URL(input, base: string | null = null): throwsUrlError(Invalid URL: …, orInvalid base URL: …whenbasedoes not parse), aTypeErroras in JS (itsnameisTypeError, ande instanceof TypeErrorholds).URL.parse(input, base = null): URL | null.URL.canParse(input, base = null).- Getters:
href protocol username password host hostname port pathname search hash origin. - Setters: everything except
origin. Invalid values are ignored, as in JS, excepthref, which throws. searchParams(get) returns a copy. Write changes back withu.searchParams = params.toString()andtoJSON()both returnhref.new URLSearchParams(init = ""): a leading?is skipped.size,get(name): string | null,getAll,has(name, value?)append,set,delete(name, value?),sort()(stable)keys(),values(),entries(): arrays, not iteratorstoString(): form encoding (space becomes+)
encodeURIComponent,encodeURI,decodeURIComponent,decodeURI: they throw the prelude'sURIError("URI malformed"), as JS: the encoders on a lone surrogate, the decoders on a bad escape or invalid UTF-8.
ts
import { URL, URLSearchParams, encodeURIComponent } from "velt/net/url";
const u = new URL("../api/items?page=2#top", "https://Example.com:443/app/v1/index.html");
console.log(u.href); // https://example.com/app/api/items?page=2#top
const params = u.searchParams;
params.set("q", "red shoes");
u.searchParams = params;
console.log(u.href); // https://example.com/app/api/items?page=2&q=red+shoes#top
console.log(new URLSearchParams("a=1&b=x+y").get("b"), encodeURIComponent("a&b/c"));Notes / gaps:
- Special schemes (
http https ws wss ftp file) get lowercased hosts, dropped default ports,\treated as/, dot-segment removal, and IPv4 normalization (127.1becomes127.0.0.1). - No IDNA/punycode: a non-ASCII host is invalid.
- IPv6 literals are validated loosely and not compressed.
- Windows drive letters in
file:URLs follow the URL spec: a path starting with/keeps the base's drive letter (/xagainstfile:///C:/p/m.tsisfile:///C:/x),..never removes it, a first segmentC|isC:(also through thepathnamesetter), a relative path that starts with one takes none of the base's path (C|/xagainstfile:///D:/p/m.tsisfile:///C:/x), and one where the host would be starts the path (file://C:/xisfile:///C:/x).