mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Signed-off-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
/**
|
|
* Escape special regex characters in a string.
|
|
*/
|
|
export function escapeRegExp(str: string): string {
|
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
}
|
|
|
|
const NEVER_MATCH = /(?!)/gi;
|
|
|
|
/**
|
|
* Build a regex that matches a given prefix followed by known multi-word names
|
|
* (longest-first to avoid partial matches). When known names are provided,
|
|
* only those names are matched — no generic fallback.
|
|
*
|
|
* When no names are available:
|
|
* - If `options.fallbackToGeneric` is true, falls back to `prefix + \S+` so
|
|
* that patterns like `#channel` still render while channel names are loading
|
|
* asynchronously (used by remarkChannelLinks).
|
|
* - Otherwise returns a never-matching regex, preventing arbitrary `@word`
|
|
* patterns from being highlighted as valid mentions when no p-tags are
|
|
* present (used by remarkMentions / buildMentionPattern).
|
|
*/
|
|
export function buildPrefixPattern(
|
|
prefix: string,
|
|
knownNames: string[],
|
|
options?: { fallbackToGeneric?: boolean },
|
|
): RegExp {
|
|
const sorted = [...new Set(knownNames)]
|
|
.filter((name) => name.trim().length > 0)
|
|
.sort((a, b) => b.length - a.length);
|
|
|
|
const escapedPrefix = escapeRegExp(prefix);
|
|
|
|
if (sorted.length === 0) {
|
|
if (options?.fallbackToGeneric) {
|
|
return new RegExp(`${escapedPrefix}\\S+`, "gi");
|
|
}
|
|
return NEVER_MATCH;
|
|
}
|
|
|
|
const nameAlternatives = sorted.map((name) => escapeRegExp(name)).join("|");
|
|
const boundary = "(?=[\\s,;.!?:)\\]}]|$)";
|
|
return new RegExp(`${escapedPrefix}(?:${nameAlternatives})${boundary}`, "gi");
|
|
}
|
|
|
|
/**
|
|
* Build a regex that matches @mentions for known multi-word names
|
|
* (longest-first to avoid partial matches). When no known names are provided,
|
|
* returns a never-matching regex — @word patterns are not highlighted unless
|
|
* they correspond to an actual p-tagged member.
|
|
*/
|
|
export function buildMentionPattern(mentionNames: string[]): RegExp {
|
|
return buildPrefixPattern("@", mentionNames);
|
|
}
|