@@ -36,32 +36,36 @@ function isTagChar(char: string): boolean {
3636// Parse tags from text and return segments
3737function parseTagsFromText ( text : string ) : Array < { type : "text" | "tag" ; value : string } > {
3838 const segments : Array < { type : "text" | "tag" ; value : string } > = [ ] ;
39+
40+ // Convert to array of code points for proper Unicode handling (emojis, etc.)
41+ const chars = [ ...text ] ;
3942 let i = 0 ;
4043
41- while ( i < text . length ) {
44+ while ( i < chars . length ) {
4245 // Check for tag pattern
43- if ( text [ i ] === "#" && i + 1 < text . length && isTagChar ( text [ i + 1 ] ) ) {
46+ if ( chars [ i ] === "#" && i + 1 < chars . length && isTagChar ( chars [ i + 1 ] ) ) {
4447 // Check if this might be a heading (## at start or after whitespace)
45- const prevChar = i > 0 ? text [ i - 1 ] : "" ;
46- const nextChar = i + 1 < text . length ? text [ i + 1 ] : "" ;
48+ const prevChar = i > 0 ? chars [ i - 1 ] : "" ;
49+ const nextChar = i + 1 < chars . length ? chars [ i + 1 ] : "" ;
4750
4851 if ( prevChar === "#" || nextChar === "#" || nextChar === " " ) {
4952 // This is a heading, not a tag
50- segments . push ( { type : "text" , value : text [ i ] } ) ;
53+ segments . push ( { type : "text" , value : chars [ i ] } ) ;
5154 i ++ ;
5255 continue ;
5356 }
5457
5558 // Extract tag content
5659 let j = i + 1 ;
57- while ( j < text . length && isTagChar ( text [ j ] ) ) {
60+ while ( j < chars . length && isTagChar ( chars [ j ] ) ) {
5861 j ++ ;
5962 }
6063
61- const tagContent = text . slice ( i + 1 , j ) ;
64+ const tagContent = chars . slice ( i + 1 , j ) . join ( "" ) ;
6265
63- // Validate tag length (must match backend MAX_TAG_LENGTH)
64- if ( tagContent . length > 0 && tagContent . length <= MAX_TAG_LENGTH ) {
66+ // Validate tag length by rune count (must match backend MAX_TAG_LENGTH)
67+ const runeCount = [ ...tagContent ] . length ;
68+ if ( runeCount > 0 && runeCount <= MAX_TAG_LENGTH ) {
6569 segments . push ( { type : "tag" , value : tagContent } ) ;
6670 i = j ;
6771 continue ;
@@ -70,10 +74,10 @@ function parseTagsFromText(text: string): Array<{ type: "text" | "tag"; value: s
7074
7175 // Regular text
7276 let j = i + 1 ;
73- while ( j < text . length && text [ j ] !== "#" ) {
77+ while ( j < chars . length && chars [ j ] !== "#" ) {
7478 j ++ ;
7579 }
76- segments . push ( { type : "text" , value : text . slice ( i , j ) } ) ;
80+ segments . push ( { type : "text" , value : chars . slice ( i , j ) . join ( "" ) } ) ;
7781 i = j ;
7882 }
7983
0 commit comments