aiostreams / packages /core /src /utils /regex.ts
f4b404's picture
Upload folder using huggingface_hub
f55c62a verified
Raw
History Blame Contribute Delete
2.36 kB
import { Cache } from './cache.js';
import { getSimpleTextHash } from './crypto.js';
const regexCache = Cache.getInstance<string, RegExp>(
'regexCache',
1_000,
'memory'
);
// parses regex and flags, also checks for existence of a custom flag - n - for negate
export function parseRegex(pattern: string): {
regex: string;
flags: string;
} {
const regexFormatMatch = /^\/(.+)\/([gimuyn]*)$/.exec(pattern);
return regexFormatMatch
? { regex: regexFormatMatch[1], flags: regexFormatMatch[2] }
: { regex: pattern, flags: '' };
}
export async function compileRegex(
pattern: string,
bypassCache: boolean = false
): Promise<RegExp> {
let { regex, flags } = parseRegex(pattern);
// the n flag is not to be used when compiling the regex
if (flags.includes('n')) {
flags = flags.replace('n', '');
}
if (bypassCache) {
return new RegExp(regex, flags);
}
return await regexCache.wrap(
(p: string, f: string) => new RegExp(p, f || undefined),
getSimpleTextHash(`${regex}|${flags}`),
30 * 24 * 60 * 60,
regex,
flags
);
}
// Build the raw pattern string used to match a list of keywords against stream
// attributes. Exposed separately so synchronous callers (e.g. the SEL parser,
// which cannot await) can produce the exact same regex shape as the async
// `formRegexFromKeywords` helper used by the keyword UI filters.
export function buildKeywordRegexPattern(keywords: string[]): string {
return `/(?:^|(?<![^ \\[(_\\-.]))(${keywords
.map((filter) => filter.replace(/[-[\]{}()*+?.,\\^$]/g, '\\$&'))
.map((filter) => filter.replace(/\s/g, '[\\s.\\-_]?'))
.join('|')})(?=[ \\)\\]_.-]|$)/i`;
}
export async function formRegexFromKeywords(
keywords: string[]
): Promise<RegExp> {
return await compileRegex(buildKeywordRegexPattern(keywords));
}
// Synchronous variant of `formRegexFromKeywords`. Produces an identical regex
// to the async version (same pattern + flags) but bypasses the async regex
// cache so it can be called from synchronous contexts such as SEL function
// implementations.
export function formRegexFromKeywordsSync(keywords: string[]): RegExp {
const { regex, flags } = parseRegex(buildKeywordRegexPattern(keywords));
const cleanedFlags = flags.includes('n') ? flags.replace('n', '') : flags;
return new RegExp(regex, cleanedFlags || undefined);
}