@@ -34,6 +34,65 @@ interface IMarkdownProps {
3434 isTranslated ?: boolean ;
3535}
3636
37+ const SKIN_TONE_MODIFIERS = [
38+ '\u{1F3FB}' , // Light Skin Tone
39+ '\u{1F3FC}' , // Medium-Light Skin Tone
40+ '\u{1F3FD}' , // Medium Skin Tone
41+ '\u{1F3FE}' , // Medium-Dark Skin Tone
42+ '\u{1F3FF}' // Dark Skin Tone
43+ ] ;
44+
45+ const isSkinToneModifier = ( unicode : string ) : boolean => {
46+ return SKIN_TONE_MODIFIERS . includes ( unicode ) ;
47+ } ;
48+
49+ const combineEmojisWithSkinTones = ( items : any [ ] ) : any [ ] => {
50+ if ( ! Array . isArray ( items ) || items . length === 0 ) return items ;
51+
52+ const combined : any [ ] = [ ] ;
53+ let i = 0 ;
54+
55+ while ( i < items . length ) {
56+ const current = items [ i ] ;
57+
58+ if (
59+ current ?. type === 'EMOJI' &&
60+ i + 1 < items . length &&
61+ items [ i + 1 ] ?. type === 'EMOJI' &&
62+ isSkinToneModifier ( items [ i + 1 ] . unicode )
63+ ) {
64+ combined . push ( {
65+ ...current ,
66+ unicode : current . unicode + items [ i + 1 ] . unicode
67+ } ) ;
68+ i += 2 ;
69+ } else {
70+ combined . push ( current ) ;
71+ i += 1 ;
72+ }
73+ }
74+
75+ return combined ;
76+ } ;
77+
78+ const processBlock = ( block : any ) : any => {
79+ if ( ! block || typeof block !== 'object' ) return block ;
80+
81+ if ( Array . isArray ( block . value ) ) {
82+ const processedValue = combineEmojisWithSkinTones ( block . value . map ( ( item : any ) => processBlock ( item ) ) ) ;
83+ return { ...block , value : processedValue } ;
84+ }
85+
86+ if ( block . items && Array . isArray ( block . items ) ) {
87+ return {
88+ ...block ,
89+ items : block . items . map ( ( item : any ) => processBlock ( item ) )
90+ } ;
91+ }
92+
93+ return block ;
94+ } ;
95+
3796const Markdown : React . FC < IMarkdownProps > = ( {
3897 msg,
3998 md,
@@ -57,6 +116,9 @@ const Markdown: React.FC<IMarkdownProps> = ({
57116 }
58117
59118 if ( isEmpty ( tokens ) ) return null ;
119+
120+ const processedTokens = tokens . map ( block => processBlock ( block ) ) ;
121+
60122 return (
61123 < View style = { { gap : 2 } } >
62124 < MarkdownContext . Provider
@@ -69,7 +131,7 @@ const Markdown: React.FC<IMarkdownProps> = ({
69131 getCustomEmoji,
70132 onLinkPress
71133 } } >
72- { tokens ?. map ( block => {
134+ { processedTokens ?. map ( block => {
73135 switch ( block . type ) {
74136 case 'BIG_EMOJI' :
75137 return < BigEmoji value = { block . value } /> ;
0 commit comments