fix: only parse complete hashtags (followed by word boundary)

Prevents incomplete hashtags from being saved during typing when
auto-save fires mid-word.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Richter
2026-02-01 22:17:39 +01:00
parent ce07d79652
commit 4a57000c38

View File

@@ -1,9 +1,11 @@
/** /**
* Extract hashtags from text content * Extract hashtags from text content
* Matches #word patterns, supporting alphanumeric and underscores * Matches #word patterns followed by word boundary (space, punctuation, or end of text)
* This prevents capturing incomplete hashtags during typing
*/ */
export function parseHashtags(text: string): string[] { export function parseHashtags(text: string): string[] {
const hashtagRegex = /#([a-zA-Z][a-zA-Z0-9_]*)/g; // Match hashtags followed by word boundary, whitespace, punctuation, or end of string
const hashtagRegex = /#([a-zA-Z][a-zA-Z0-9_]*)(?=[\s\p{P}]|$)/gu;
const matches = text.matchAll(hashtagRegex); const matches = text.matchAll(hashtagRegex);
const tags = new Set<string>(); const tags = new Set<string>();
@@ -17,6 +19,7 @@ export function parseHashtags(text: string): string[] {
/** /**
* Highlight hashtags in text for display * Highlight hashtags in text for display
* Returns HTML with hashtags wrapped in styled spans * Returns HTML with hashtags wrapped in styled spans
* Only highlights complete hashtags (followed by space, punctuation, or end)
*/ */
export function highlightHashtags(text: string): string { export function highlightHashtags(text: string): string {
const escaped = text const escaped = text
@@ -25,7 +28,7 @@ export function highlightHashtags(text: string): string {
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
return escaped.replace( return escaped.replace(
/#([a-zA-Z][a-zA-Z0-9_]*)/g, /#([a-zA-Z][a-zA-Z0-9_]*)(?=[\s\p{P}]|$)/gu,
'<span class="text-blue-600 font-medium">#$1</span>' '<span class="text-blue-600 font-medium">#$1</span>'
); );
} }