@@ -89,15 +89,23 @@ export function textareaSplitLines(value: string, pos: number): TextLinesBuffer
8989}
9090
9191function markdownReformatListNumbers ( linesBuf : TextLinesBuffer , indention : string ) {
92- const re = new RegExp ( `^${ indention } ([0-9]+)\\.` ) ;
93- let firstLineIdx = 0 ;
92+ const reDeeperIndention = new RegExp ( `^${ indention } \\s+` ) ;
93+ const reSameLevel = new RegExp ( `^${ indention } ([0-9]+)\\.` ) ;
94+ let firstLineIdx : number ;
9495 for ( firstLineIdx = linesBuf . posLineIndex - 1 ; firstLineIdx >= 0 ; firstLineIdx -- ) {
95- if ( ! re . test ( linesBuf . lines [ firstLineIdx ] ) ) break ;
96+ const line = linesBuf . lines [ firstLineIdx ] ;
97+ if ( ! reDeeperIndention . test ( line ) && ! reSameLevel . test ( line ) ) break ;
9698 }
9799 firstLineIdx ++ ;
100+ let num = 1 ;
98101 for ( let i = firstLineIdx ; i < linesBuf . lines . length ; i ++ ) {
99- if ( ! re . test ( linesBuf . lines [ i ] ) ) break ;
100- linesBuf . lines [ i ] = `${ indention } ${ i - firstLineIdx + 1 } .${ linesBuf . lines [ i ] . replace ( re , '' ) } ` ;
102+ const line = linesBuf . lines [ i ] ;
103+ const sameLevel = reSameLevel . test ( line ) ;
104+ if ( ! sameLevel && ! reDeeperIndention . test ( line ) ) break ;
105+ if ( sameLevel ) {
106+ linesBuf . lines [ i ] = `${ indention } ${ num } .${ line . replace ( reSameLevel , '' ) } ` ;
107+ num ++ ;
108+ }
101109 }
102110 linesBuf . lengthBeforePosLine = 0 ;
103111 for ( let i = 0 ; i < linesBuf . posLineIndex ; i ++ ) {
@@ -107,36 +115,30 @@ function markdownReformatListNumbers(linesBuf: TextLinesBuffer, indention: strin
107115}
108116
109117export function markdownHandleListNumbers ( tvs : TextareaValueSelection ) : MarkdownHandleListNumbersResult {
110- const ret : MarkdownHandleListNumbersResult = { handled : false } ;
111- if ( tvs . selEnd !== tvs . selStart ) return ret ; // do not process when there is a selection
112-
113- const value = tvs . value ;
114- // find the current line
115- // * if selStart is 0, lastIndexOf(..., -1) is the same as lastIndexOf(..., 0)
116- // * if lastIndexOf reruns -1, lineStart is 0 and it is still correct.
117- const lineStart = value . lastIndexOf ( '\n' , tvs . selStart - 1 ) + 1 ;
118- let lineEnd = value . indexOf ( '\n' , tvs . selStart ) ;
119- lineEnd = lineEnd < 0 ? value . length : lineEnd ;
120- let line = value . slice ( lineStart , lineEnd ) ;
121- if ( ! line ) return ; // if the line is empty, do nothing, let the browser handle it
118+ const unhandled : MarkdownHandleListNumbersResult = { handled : false } ;
119+ if ( tvs . selEnd !== tvs . selStart ) return unhandled ; // do not process when there is a selection
120+
121+ const linesBuf = textareaSplitLines ( tvs . value , tvs . selStart ) ;
122+ let line = linesBuf . lines [ linesBuf . posLineIndex ] ?? '' ;
123+ if ( ! line ) return unhandled ; // if the line is empty, do nothing, let the browser handle it
122124
123125 // parse the indention
124126 const indention = / ^ \s * / . exec ( line ) [ 0 ] ;
125127 line = line . slice ( indention . length ) ;
128+ if ( linesBuf . inlinePos <= indention . length ) return unhandled ; // if cursor is at the indention, do nothing, let the browser handle it
126129
127130 // parse the prefixes: "1. ", "- ", "* ", there could also be " [ ] " or " [x] " for task lists
128131 // there must be a space after the prefix because none of "1.foo" / "-foo" is a list item
129132 const prefixMatch = / ^ ( [ 0 - 9 ] + \. | [ - * ] ) ( \s \[ ( [ x ] ) \] ) ? \s / . exec ( line ) ;
130133 let prefix = '' ;
131134 if ( prefixMatch ) {
132135 prefix = prefixMatch [ 0 ] ;
133- if ( lineStart + prefix . length > tvs . selStart ) prefix = '' ; // do not add new line if cursor is at prefix
136+ if ( prefix . length > linesBuf . inlinePos ) prefix = '' ; // do not add new line if cursor is at prefix
134137 }
135138
136139 line = line . slice ( prefix . length ) ;
137- if ( ! indention && ! prefix ) return ret ; // if no indention and no prefix, do nothing, let the browser handle it
140+ if ( ! indention && ! prefix ) return unhandled ; // if no indention and no prefix, do nothing, let the browser handle it
138141
139- const linesBuf = textareaSplitLines ( value , tvs . selStart ) ;
140142 if ( ! line ) {
141143 // clear current line if we only have i.e. '1. ' and the user presses enter again to finish creating a list
142144 linesBuf . lines [ linesBuf . posLineIndex ] = '' ;
0 commit comments