shelving
Version:
Toolkit for using data in JavaScript.
73 lines (72 loc) • 3.38 kB
JavaScript
import { RequiredError } from "../error/RequiredError.js";
import { ValueError } from "../error/ValueError.js";
import { getArray } from "./array.js";
/** Regular expression that always matches everything. */
export const ALWAYS_REGEXP = /^.*$/;
/** Regular expression that never matches anything. */
export const NEVER_REGEXP = /^(?=a)a/;
/** Is an unknown value a `RegExp` instance? */
export function isRegExp(value) {
return value instanceof RegExp;
}
/** Assert that an unknown value is a `RegExp` instance. */
export function assertRegExp(value) {
if (!(value instanceof RegExp))
throw new RequiredError("Must be regular expression", { received: value, caller: assertRegExp });
}
export function getRegExp(pattern, flags) {
return typeof pattern === "string" ? new RegExp(pattern, flags) : pattern;
}
/** Convert a regular expression to its string source. */
export function getRegExpSource(regexp) {
return typeof regexp === "string" ? regexp : regexp.source;
}
/** Escape special characters in a string regular expression. */
export function escapeRegExp(pattern) {
return pattern.replace(REPLACE_ESCAPED, "\\$&");
}
const REPLACE_ESCAPED = /[-[\]/{}()*+?.\\^$|]/g;
/** Create regular expression that matches any of a list of other expressions. */
export function createRegExpAny(patterns, flags) {
const arr = getArray(patterns).filter(Boolean);
// If there are no patterns to match against then _no_ string can ever match against any of nothing.
if (!arr.length)
return NEVER_REGEXP;
// Create RegExp using multiple joined matches like `(?:AAA)|(?:BBB)`
return new RegExp(`(?:${getArray(patterns).map(getRegExpSource).join(")|(?:")})`, flags);
}
/** Create regular expression that matches all of a list of other expressions. */
export function createRegExpAll(patterns, flags) {
const arr = getArray(patterns).filter(Boolean);
// If there are no patterns to match against then _every_ string will match against the entire list of nothing.
if (!arr.length)
return ALWAYS_REGEXP;
// Create RegExp using multiple lookaheads like `^(?=.*?(?:AAA))(?=.*?(?:BBB))`
return new RegExp(`^(?=.*?(?:${getArray(patterns).map(getRegExpSource).join("))(?=.*?(?:")}))`, flags);
}
/** Match function for finding strings that match against regular expressions (use with `filter()` to positively filter iterable sets of items). */
export function isMatch(str, regexp) {
return regexp.test(str);
}
/** Match function for finding strings that match against regular expressions (use with `filter()` to negatively filter iterable sets of items). */
export function notMatch(str, regexp) {
return !regexp.test(str);
}
export function getMatch(str, regexp) {
return regexp.exec(str) || undefined;
}
export function requireMatch(str, regexp) {
const match = getMatch(str, regexp);
if (!match)
throw new ValueError("Must match regular expression", { received: str, expected: regexp, caller: requireMatch });
return match;
}
export function getMatchGroups(str, regexp) {
return regexp.exec(str)?.groups || undefined;
}
export function requireMatchGroups(str, regexp) {
const groups = getMatchGroups(str, regexp);
if (!groups)
throw new ValueError("Must match regular expression", { received: str, expected: regexp, caller: requireMatchGroups });
return groups;
}