57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
export type CompiledGlobPattern =
|
|
| { kind: "all" }
|
|
| { kind: "exact"; value: string }
|
|
| { kind: "regex"; value: RegExp };
|
|
|
|
function escapeRegex(value: string) {
|
|
// Standard "escape string for regex literal" pattern.
|
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
}
|
|
|
|
export function compileGlobPattern(params: {
|
|
raw: string;
|
|
normalize: (value: string) => string;
|
|
}): CompiledGlobPattern {
|
|
const normalized = params.normalize(params.raw);
|
|
if (!normalized) {
|
|
return { kind: "exact", value: "" };
|
|
}
|
|
if (normalized === "*") {
|
|
return { kind: "all" };
|
|
}
|
|
if (!normalized.includes("*")) {
|
|
return { kind: "exact", value: normalized };
|
|
}
|
|
return {
|
|
kind: "regex",
|
|
value: new RegExp(`^${escapeRegex(normalized).replaceAll("\\*", ".*")}$`),
|
|
};
|
|
}
|
|
|
|
export function compileGlobPatterns(params: {
|
|
raw?: string[] | undefined;
|
|
normalize: (value: string) => string;
|
|
}): CompiledGlobPattern[] {
|
|
if (!Array.isArray(params.raw)) {
|
|
return [];
|
|
}
|
|
return params.raw
|
|
.map((raw) => compileGlobPattern({ raw, normalize: params.normalize }))
|
|
.filter((pattern) => pattern.kind !== "exact" || pattern.value);
|
|
}
|
|
|
|
export function matchesAnyGlobPattern(value: string, patterns: CompiledGlobPattern[]): boolean {
|
|
for (const pattern of patterns) {
|
|
if (pattern.kind === "all") {
|
|
return true;
|
|
}
|
|
if (pattern.kind === "exact" && value === pattern.value) {
|
|
return true;
|
|
}
|
|
if (pattern.kind === "regex" && pattern.value.test(value)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|