@@ -95,9 +95,33 @@ function processParent(parent: Parent, source: string) {
9595 }
9696}
9797
98+ function getInnerText ( node : Node ) : string {
99+ if ( isTextNode ( node ) ) return node . value ;
100+ if ( 'children' in node ) {
101+ const children = ( node as Parent ) . children ;
102+ if ( children . length > 0 ) return getInnerText ( children [ 0 ] ) ;
103+ }
104+ return '' ;
105+ }
106+
107+ function getInnerTextEnd ( node : Node ) : string {
108+ if ( isTextNode ( node ) ) return node . value ;
109+ if ( 'children' in node ) {
110+ const children = ( node as Parent ) . children ;
111+ if ( children . length > 0 )
112+ return getInnerTextEnd ( children [ children . length - 1 ] ) ;
113+ }
114+ return '' ;
115+ }
116+
98117/**
99118 * Checks whether the emphasis/strong node at `index` within `parent`
100119 * is an intraword usage of underscore delimiters.
120+ *
121+ * A node is intraword when at least one side has an alphanumeric text
122+ * neighbor AND the inner content on the corresponding delimiter side
123+ * also touches word characters — proving the underscores are embedded
124+ * in a word rather than used as formatting.
101125 */
102126function isIntraword ( parent : Parent , index : number , source : string ) : boolean {
103127 const node = parent . children [ index ] ;
@@ -112,19 +136,38 @@ function isIntraword(parent: Parent, index: number, source: string): boolean {
112136 const next =
113137 index < parent . children . length - 1 ? parent . children [ index + 1 ] : null ;
114138
115- const prevEndsWithAlpha =
116- prev != null &&
117- isTextNode ( prev ) &&
118- prev . value . length > 0 &&
119- isAlphanumeric ( prev . value [ prev . value . length - 1 ] ) ;
139+ const prevChar =
140+ prev != null && isTextNode ( prev ) && prev . value . length > 0
141+ ? prev . value [ prev . value . length - 1 ]
142+ : null ;
143+
144+ const nextChar =
145+ next != null && isTextNode ( next ) && next . value . length > 0
146+ ? next . value [ 0 ]
147+ : null ;
148+
149+ const prevIsAlpha = prevChar != null && isAlphanumeric ( prevChar ) ;
150+ const nextIsAlpha = nextChar != null && isAlphanumeric ( nextChar ) ;
120151
121- const nextStartsWithAlpha =
122- next != null &&
123- isTextNode ( next ) &&
124- next . value . length > 0 &&
125- isAlphanumeric ( next . value [ 0 ] ) ;
152+ // Both sides flanked by alphanumeric — classic intraword (e.g. `foo__bar__baz`)
153+ if ( prevIsAlpha && nextIsAlpha ) return true ;
154+
155+ // One-sided: prev is alpha or underscore, no alpha next — check inner text
156+ // starts with alpha (e.g. `Lorem__ipsum__` or `Lorem__ipsum_`)
157+ if ( prevIsAlpha || prevChar === '_' ) {
158+ const inner = getInnerText ( node ) ;
159+ if ( inner . length > 0 && isAlphanumeric ( inner [ 0 ] ) ) return true ;
160+ }
161+
162+ // One-sided: next is alpha or underscore, no alpha prev — check inner text
163+ // ends with alpha (e.g. `__Lorem__ipsum` or `_Lorem__ipsum`)
164+ if ( nextIsAlpha || nextChar === '_' ) {
165+ const inner = getInnerTextEnd ( node ) ;
166+ if ( inner . length > 0 && isAlphanumeric ( inner [ inner . length - 1 ] ) )
167+ return true ;
168+ }
126169
127- return prevEndsWithAlpha && nextStartsWithAlpha ;
170+ return false ;
128171}
129172
130173function mergeAdjacentText ( parent : Parent ) {
0 commit comments