@@ -19,6 +19,11 @@ import {getTextInLanguage} from '../lang/helpers';
1919
2020const LRU = new QuickLRU ( { maxSize : 200 } ) ;
2121
22+ type PositionPlusEmptyIndicator = {
23+ position : Position ,
24+ isEmpty : boolean ,
25+ }
26+
2227export enum MDAstTypes {
2328 Link = 'link' ,
2429 Footnote = 'footnoteDefinition' ,
@@ -107,27 +112,40 @@ export function getPositions(type: MDAstTypes, text: string): Position[] {
107112/**
108113 * Gets the positions of the list item text in the given text.
109114 * @param {string } text - The markdown text
110- * @return {Position[] } The positions of the list item text in the given text
115+ * @param {boolean } includeEmptyNodes - Whether or not empty list items should be
116+ * returned to be handled by the calling function
117+ * @return {PositionPlusEmptyIndicator[] } The positions of the list item text in the given text
118+ * with a status as to whether or not they are empty
111119 */
112- function getListItemTextPositions ( text : string ) : Position [ ] {
120+ function getListItemTextPositions ( text : string , includeEmptyNodes : boolean = false ) : Position [ ] {
113121 const ast = parseTextToAST ( text ) ;
114- const positions : Position [ ] = [ ] ;
122+ const positions : PositionPlusEmptyIndicator [ ] = [ ] ;
115123 visit ( ast , MDAstTypes . ListItem as string , ( node ) => {
116124 // @ts -ignore the fact that not all nodes have a children property since I am skipping any that do not
117- if ( ! node . children ) {
125+ if ( ! node . children || node . children . length === 0 ) {
126+ if ( includeEmptyNodes ) {
127+ positions . push ( {
128+ position : node . position ,
129+ isEmpty : true ,
130+ } ) ;
131+ }
132+
118133 return ;
119134 }
120135
121136 // @ts -ignore the fact that not all nodes have a children property since I have already exited the function if that is the case
122137 for ( const childNode of node . children ) {
123138 if ( childNode . type === ( MDAstTypes . Paragraph as string ) ) {
124- positions . push ( childNode . position ) ;
139+ positions . push ( {
140+ position : childNode . position ,
141+ isEmpty : false ,
142+ } ) ;
125143 }
126144 }
127145 } ) ;
128146
129147 // Sort positions by start position in reverse order
130- positions . sort ( ( a , b ) => b . start . offset - a . start . offset ) ;
148+ positions . sort ( ( a , b ) => b . position . start . offset - a . position . start . offset ) ;
131149 return positions ;
132150}
133151
@@ -587,29 +605,40 @@ export function updateBoldText(text: string, func:(text: string) => string): str
587605 return text ;
588606}
589607
590- export function updateListItemText ( text : string , func :( text : string ) => string ) : string {
591- const positions : Position [ ] = getListItemTextPositions ( text ) ;
608+ export function updateListItemText ( text : string , func :( text : string ) => string , includeEmptyNodes : boolean = false ) : string {
609+ const positions : PositionPlusEmptyIndicator [ ] = getListItemTextPositions ( text , includeEmptyNodes ) ;
592610
593611 for ( const position of positions ) {
594- let startIndex = position . start . offset ;
595- // get the actual start of the list item leaving only 1 whitespace between the indicator and the text
596- while ( startIndex > 0 && text . charAt ( startIndex - 1 ) . trim ( ) === '' ) {
597- startIndex -- ;
598- }
599- // keep a single space for the indicator
600- if ( startIndex === 0 || text . charAt ( startIndex - 1 ) . trim ( ) != '' ) {
612+ let startIndex = position . position . start . offset ;
613+ if ( position . isEmpty ) {
614+ // get the actual start of the list item leaving only 1 whitespace between the indicator and the text
615+ while ( startIndex < position . position . end . offset && text . charAt ( startIndex ) . trim ( ) !== '' ) {
616+ startIndex ++ ;
617+ }
618+
601619 startIndex ++ ;
620+ } else {
621+ // get the actual start of the list item leaving only 1 whitespace between the indicator and the text
622+ while ( startIndex > 0 && text . charAt ( startIndex - 1 ) . trim ( ) === '' ) {
623+ startIndex -- ;
624+ }
625+
626+ // keep a single space for the indicator
627+ if ( startIndex === 0 || text . charAt ( startIndex - 1 ) . trim ( ) != '' ) {
628+ startIndex ++ ;
629+ }
602630 }
603631
604- let listText = text . substring ( startIndex , position . end . offset ) ;
632+ let listText = text . substring ( startIndex , position . position . end . offset ) ;
605633 // for some reason some checklists are not getting treated as such and this causes the task indicator to be included in the text
606634 if ( checklistBoxStartsTextRegex . test ( listText ) ) {
607635 startIndex += 4 ;
608636 listText = listText . substring ( 4 ) ;
609637 }
638+
610639 listText = func ( listText ) ;
611640
612- text = replaceTextBetweenStartAndEndWithNewValue ( text , startIndex , position . end . offset , listText ) ;
641+ text = replaceTextBetweenStartAndEndWithNewValue ( text , startIndex , position . position . end . offset , listText ) ;
613642 }
614643
615644 return text ;
0 commit comments