shelving
Version:
Toolkit for using data in JavaScript.
50 lines (49 loc) • 1.9 kB
JavaScript
import { formatURL } from "../util/format.js";
import { sanitizeWord } from "../util/string.js";
import { HTTP_SCHEMES } from "../util/uri.js";
import { getURL } from "../util/url.js";
import { NULLABLE } from "./NullableSchema.js";
import { StringSchema } from "./StringSchema.js";
/**
* Type of `StringSchema` that defines a valid URL string.
* - Checks URL scheme against a whitelist (always), and checks URL domain against a whitelist (optional).
* - URLs are limited to 512 characters, but generally these won't be data: URIs so this is a reasonable limit.
*/
export class URLSchema extends StringSchema {
base;
schemes;
constructor({ one = "URL", title = "URL", base, schemes = HTTP_SCHEMES, ...options }) {
super({
one,
title,
...options,
input: "url",
min: 1,
max: 512,
rows: 1,
});
this.base = getURL(base)?.href;
this.schemes = schemes;
}
// Override to validate the URL and check the schemes and hosts against the whitelists.
validate(unsafeValue) {
const str = super.validate(unsafeValue);
const url = getURL(str, this.base);
if (!url)
throw str ? `Invalid ${this.one} format` : "Required";
if (this.schemes && !this.schemes.includes(url.protocol))
throw `Invalid ${this.one} scheme`;
return url.href;
}
sanitize(str) {
// URLs never contain whitespace (a real space must be `%20`-encoded), so strip it entirely.
return sanitizeWord(str);
}
format(value) {
return formatURL(value, this.base, this.format);
}
}
/** Valid URL string, e.g. `https://www.google.com` */
export const URL_SCHEMA = new URLSchema({});
/** Valid URL string, e.g. `https://www.google.com`, or `null` */
export const NULLABLE_URL_SCHEMA = NULLABLE(URL_SCHEMA);