Files
omniai-web/src/utils/mentionTrigger.ts
T

50 lines
1.6 KiB
TypeScript
Raw Normal View History

2026-06-02 12:38:01 +08:00
/**
* Shared mention trigger detection.
*
* Detects when the user has typed "@" followed by an optional query
* at the cursor position, and returns the match info for opening
* a mention panel.
*/
/** Characters that BLOCK @ trigger (only @ itself, to prevent @@). */
const BLOCKED_BEFORE_AT = /[@]/;
export interface MentionTriggerMatch {
/** Index of the @ character in the full text. */
atIndex: number;
/** The query text after @ (may be empty). */
query: string;
}
/**
* Check whether the text before the cursor contains an active @ mention trigger.
*
* Rules:
* - @ must be at position 0, or preceded by a boundary character
* (whitespace, Chinese/English punctuation, brackets).
* - The query (text after @ up to the cursor) must not contain
* any boundary character or space.
* - Returns null if no trigger is found.
*/
export function detectMentionTrigger(textBeforeCursor: string): MentionTriggerMatch | null {
const atIdx = textBeforeCursor.lastIndexOf("@");
if (atIdx < 0) return null;
// @ must be at start or not preceded by another @
if (atIdx > 0 && BLOCKED_BEFORE_AT.test(textBeforeCursor[atIdx - 1])) {
return null;
}
const query = textBeforeCursor.slice(atIdx + 1);
// Query must not contain spaces or punctuation that would break a mention token
2026-06-09 12:02:30 +08:00
if (/[\s,。、;:!??!.,;:(){}[\]<>""''《》【】@]/.test(query)) {
2026-06-02 12:38:01 +08:00
return null;
}
return { atIndex: atIdx, query };
}
/** Token pattern for @图片1, @视频1, @文本1, @音频1, @附件1, @素材1, etc. */
export const MENTION_TOKEN_RE = /@(?:图片|视频|文本|音频|附件|素材)\d+/g;