@@ -763,27 +763,40 @@ const ImageLightbox: React.FC<{ src: string; alt: string; onClose: () => void }>
763763} ;
764764
765765/**
766- * Renders inline markdown: **bold**, *italic*, `code`, [links](url)
766+ * Renders inline markdown: **bold**, *italic*, _italic_, `code`, [links](url)
767767 */
768768const InlineMarkdown : React . FC < { text : string ; onOpenLinkedDoc ?: ( path : string ) => void ; imageBaseDir ?: string ; onImageClick ?: ( src : string , alt : string ) => void } > = ( { text, onOpenLinkedDoc, imageBaseDir, onImageClick } ) => {
769769 const parts : React . ReactNode [ ] = [ ] ;
770770 let remaining = text ;
771771 let key = 0 ;
772+ let previousChar = '' ;
772773
773774 while ( remaining . length > 0 ) {
774775 // Bold: **text** ([\s\S]+? allows matching across hard line breaks)
775776 let match = remaining . match ( / ^ \* \* ( [ \s \S ] + ?) \* \* / ) ;
776777 if ( match ) {
777778 parts . push ( < strong key = { key ++ } className = "font-semibold" > < InlineMarkdown imageBaseDir = { imageBaseDir } onImageClick = { onImageClick } text = { match [ 1 ] } onOpenLinkedDoc = { onOpenLinkedDoc } /> </ strong > ) ;
778779 remaining = remaining . slice ( match [ 0 ] . length ) ;
780+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
779781 continue ;
780782 }
781783
782- // Italic: *text*
784+ // Italic: *text* or _text_ (avoid intraword underscores)
783785 match = remaining . match ( / ^ \* ( [ \s \S ] + ?) \* / ) ;
784786 if ( match ) {
785787 parts . push ( < em key = { key ++ } > < InlineMarkdown imageBaseDir = { imageBaseDir } onImageClick = { onImageClick } text = { match [ 1 ] } onOpenLinkedDoc = { onOpenLinkedDoc } /> </ em > ) ;
786788 remaining = remaining . slice ( match [ 0 ] . length ) ;
789+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
790+ continue ;
791+ }
792+
793+ match = ! / \w / . test ( previousChar )
794+ ? remaining . match ( / ^ _ ( [ ^ _ \s ] (?: [ \s \S ] * ?[ ^ _ \s ] ) ? ) _ (? ! \w ) / )
795+ : null ;
796+ if ( match ) {
797+ parts . push ( < em key = { key ++ } > < InlineMarkdown imageBaseDir = { imageBaseDir } onImageClick = { onImageClick } text = { match [ 1 ] } onOpenLinkedDoc = { onOpenLinkedDoc } /> </ em > ) ;
798+ remaining = remaining . slice ( match [ 0 ] . length ) ;
799+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
787800 continue ;
788801 }
789802
@@ -796,6 +809,7 @@ const InlineMarkdown: React.FC<{ text: string; onOpenLinkedDoc?: (path: string)
796809 </ code >
797810 ) ;
798811 remaining = remaining . slice ( match [ 0 ] . length ) ;
812+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
799813 continue ;
800814 }
801815
@@ -830,6 +844,7 @@ const InlineMarkdown: React.FC<{ text: string; onOpenLinkedDoc?: (path: string)
830844 ) ;
831845 }
832846 remaining = remaining . slice ( match [ 0 ] . length ) ;
847+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
833848 continue ;
834849 }
835850
@@ -850,6 +865,7 @@ const InlineMarkdown: React.FC<{ text: string; onOpenLinkedDoc?: (path: string)
850865 />
851866 ) ;
852867 remaining = remaining . slice ( match [ 0 ] . length ) ;
868+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
853869 continue ;
854870 }
855871
@@ -905,6 +921,7 @@ const InlineMarkdown: React.FC<{ text: string; onOpenLinkedDoc?: (path: string)
905921 ) ;
906922 }
907923 remaining = remaining . slice ( match [ 0 ] . length ) ;
924+ previousChar = match [ 0 ] [ match [ 0 ] . length - 1 ] || previousChar ;
908925 continue ;
909926 }
910927
@@ -917,17 +934,21 @@ const InlineMarkdown: React.FC<{ text: string; onOpenLinkedDoc?: (path: string)
917934 }
918935 parts . push ( < br key = { key ++ } /> ) ;
919936 remaining = remaining . slice ( match . index + match [ 0 ] . length ) ;
937+ previousChar = '\n' ;
920938 continue ;
921939 }
922940
923941 // Find next special character or consume one regular character
924- const nextSpecial = remaining . slice ( 1 ) . search ( / [ \* ` \[ ! ] / ) ;
942+ const nextSpecial = remaining . slice ( 1 ) . search ( / [ \* _ ` \[ ! ] / ) ;
925943 if ( nextSpecial === - 1 ) {
926944 parts . push ( remaining ) ;
945+ previousChar = remaining [ remaining . length - 1 ] || previousChar ;
927946 break ;
928947 } else {
929- parts . push ( remaining . slice ( 0 , nextSpecial + 1 ) ) ;
948+ const plainText = remaining . slice ( 0 , nextSpecial + 1 ) ;
949+ parts . push ( plainText ) ;
930950 remaining = remaining . slice ( nextSpecial + 1 ) ;
951+ previousChar = plainText [ plainText . length - 1 ] || previousChar ;
931952 }
932953 }
933954
0 commit comments