05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 1 | import type { Mention } from './mentions'; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 2 | |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 3 | export interface MarkPart { |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 4 | text: string; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 5 | mark: boolean; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 6 | } |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 7 | |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 8 | /** The composer text split so picked mention names and emote shortcodes can be highlighted behind the textarea. */ |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 9 | export function markMentions(text: string, mentions: Mention[], extra: string[] = []): MarkPart[] { |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 10 | const names = [...new Set([...mentions.map((m) => m.text), ...extra].filter(Boolean))].sort((a, b) => b.length - a.length); |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 11 | if (!names.length || !text) return [{ text, mark: false }]; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 12 | const parts: MarkPart[] = []; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 13 | let rest = text; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 14 | while (rest) { |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 15 | let at = -1; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 16 | let hit = ''; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 17 | for (const name of names) { |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 18 | const i = rest.indexOf(name); |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 19 | if (i >= 0 && (at < 0 || i < at)) { |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 20 | at = i; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 21 | hit = name; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 22 | } |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 23 | } |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 24 | if (at < 0) { |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 25 | parts.push({ text: rest, mark: false }); |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 26 | break; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 27 | } |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 28 | if (at > 0) parts.push({ text: rest.slice(0, at), mark: false }); |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 29 | parts.push({ text: hit, mark: true }); |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 30 | rest = rest.slice(at + hit.length); |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 31 | } |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 32 | return parts; |
05a48e9e7942 | atagen | 2026-10-24 09:32 UTC | 33 | } |