diff --git a/resources/tailwind-app/components/Status/StatusCard.vue b/resources/tailwind-app/components/Status/StatusCard.vue index 64aec95b9..efff12523 100644 --- a/resources/tailwind-app/components/Status/StatusCard.vue +++ b/resources/tailwind-app/components/Status/StatusCard.vue @@ -165,42 +165,34 @@ watch( { immediate: true }, ); -function escapeHtml(s: string): string { - return s - .replaceAll('&', '&') - .replaceAll('<', '<') - .replaceAll('>', '>') - .replaceAll('"', '"') - .replaceAll("'", '''); -} +type BodySegment = { text: string; username?: string }; -const enrichedBody = computed(() => { +const bodySegments = computed(() => { const body = statusObject.value.body ?? ''; const mentions: MentionDto[] = (statusObject.value as unknown as { bodyMentions?: MentionDto[] }).bodyMentions ?? []; - if (!body) return ''; - if (!mentions.length) return escapeHtml(body); + if (!body) return []; const userMap = new Map(); for (const m of mentions) { if (m.user?.username) userMap.set(m.user.username.toLowerCase(), m.user); } - if (!userMap.size) return escapeHtml(body); + if (!userMap.size) return [{ text: body }]; const mentionRegex = /@(\w+)/g; - let result = ''; + const segments: BodySegment[] = []; let lastIndex = 0; let match: RegExpExecArray | null; while ((match = mentionRegex.exec(body)) !== null) { const user = userMap.get(match[1].toLowerCase()); if (!user) continue; - result += escapeHtml(body.slice(lastIndex, match.index)); - result += `${escapeHtml(match[0])}`; + if (match.index > lastIndex) segments.push({ text: body.slice(lastIndex, match.index) }); + segments.push({ text: match[0], username: user.username }); lastIndex = match.index + match[0].length; } - result += escapeHtml(body.slice(lastIndex)); - return result; + if (lastIndex < body.length) segments.push({ text: body.slice(lastIndex) }); + return segments; }); function toggleLike() { @@ -366,12 +358,19 @@ const inProgress = computed(() => progress.value > 0 && progress.value < 100); -

+ > + +

- + - +