forked from BRETT/BRETT
38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
export interface MentionUser {
|
|
id: number
|
|
name: string
|
|
color: string | null
|
|
}
|
|
|
|
export function activeMention(text: string, caret: number) {
|
|
const before = text.slice(0, caret)
|
|
const start = before.lastIndexOf('@')
|
|
if (start < 0 || (start > 0 && !/[\s([{]/.test(before[start - 1]!))) return null
|
|
const query = before.slice(start + 1)
|
|
if (query.length > 50 || /[\r\n@]/.test(query)) return null
|
|
return { start, end: caret, query }
|
|
}
|
|
|
|
export function mentionParts(text: string, users: MentionUser[]) {
|
|
const names = [...users].sort((a, b) => b.name.length - a.name.length)
|
|
const parts: { text: string, user?: MentionUser }[] = []
|
|
let last = 0
|
|
for (let i = 0; i < text.length; i++) {
|
|
if (text[i] !== '@' || (i > 0 && !/[\s([{]/.test(text[i - 1]!))) continue
|
|
const user = names.find(u => text.slice(i + 1, i + 1 + u.name.length).toLowerCase() === u.name.toLowerCase()
|
|
&& !/[\p{L}\p{N}_-]/u.test(text[i + 1 + u.name.length] ?? ''))
|
|
if (!user) continue
|
|
if (i > last) parts.push({ text: text.slice(last, i) })
|
|
last = i + 1 + user.name.length
|
|
parts.push({ text: text.slice(i, last), user })
|
|
i = last - 1
|
|
}
|
|
if (last < text.length) parts.push({ text: text.slice(last) })
|
|
return parts
|
|
}
|
|
|
|
export function mentionedUserIds(content: string, users: MentionUser[]) {
|
|
return new Set(content.split(/https?:\/\/[^\s<>"']+/g)
|
|
.flatMap(text => mentionParts(text, users).flatMap(part => part.user ? [part.user.id] : [])))
|
|
}
|