@@ -6,6 +6,36 @@ import { LINE_SEPARATOR } from './special-characters';
66import { normaliseFormats } from './normalise-formats' ;
77import { getLineIndex } from './get-line-index' ;
88
9+ /**
10+ * Gets the line index of the first previous list item with higher indentation.
11+ *
12+ * @param {Object } value Value to search.
13+ * @param {number } lineIndex Line index of the list item to compare with.
14+ *
15+ * @return {boolean } The line index.
16+ */
17+ function getTargetLevelLineIndex ( { text, formats } , lineIndex ) {
18+ const startFormats = formats [ lineIndex ] || [ ] ;
19+
20+ let index = lineIndex ;
21+
22+ while ( index -- >= 0 ) {
23+ if ( text [ index ] !== LINE_SEPARATOR ) {
24+ continue ;
25+ }
26+
27+ const formatsAtIndex = formats [ index ] || [ ] ;
28+
29+ // Return the first line index that is one level higher. If the level is
30+ // lower or equal, there is no result.
31+ if ( formatsAtIndex . length === startFormats . length + 1 ) {
32+ return index ;
33+ } else if ( formatsAtIndex . length <= startFormats . length ) {
34+ return ;
35+ }
36+ }
37+ }
38+
939/**
1040 * Indents any selected list items if possible.
1141 *
@@ -23,62 +53,39 @@ export function indentListItems( value, rootFormat ) {
2353 }
2454
2555 const { text, formats, start, end } = value ;
56+ const previousLineIndex = getLineIndex ( value , lineIndex ) ;
2657 const formatsAtLineIndex = formats [ lineIndex ] || [ ] ;
27- const targetFormats = formats [ getLineIndex ( value , lineIndex ) ] || [ ] ;
58+ const formatsAtPreviousLineIndex = formats [ previousLineIndex ] || [ ] ;
2859
2960 // The the indentation of the current line is greater than previous line,
3061 // then the line cannot be furter indented.
31- if ( formatsAtLineIndex . length > targetFormats . length ) {
62+ if ( formatsAtLineIndex . length > formatsAtPreviousLineIndex . length ) {
3263 return value ;
3364 }
3465
3566 const newFormats = formats . slice ( ) ;
67+ const targetLevelLineIndex = getTargetLevelLineIndex ( value , lineIndex ) ;
3668
3769 for ( let index = lineIndex ; index < end ; index ++ ) {
3870 if ( text [ index ] !== LINE_SEPARATOR ) {
3971 continue ;
4072 }
4173
42- // If the indentation of the previous line is the same as the current
43- // line, then duplicate the type and append all current types. E.g.
44- //
45- // 1. one
46- // 2. two <= Selected
47- // * three <= Selected
48- //
49- // should become:
50- //
51- // 1. one
52- // 1. two <= Selected
53- // * three <= Selected
54- //
55- // ^ Inserted list
56- //
57- // Otherwise take the target formats and append traling lists. E.g.
58- //
59- // 1. one
60- // * target
61- // 2. two <= Selected
62- // * three <= Selected
63- //
64- // should become:
65- //
66- // 1. one
67- // * target
68- // * two <= Selected
69- // * three <= Selected
70- //
71- if ( targetFormats . length === formatsAtLineIndex . length ) {
74+ // Get the previous list, and if there's a child list, take over the
75+ // formats. If not, duplicate the last level and create a new level.
76+ if ( targetLevelLineIndex ) {
77+ const targetFormats = formats [ targetLevelLineIndex ] || [ ] ;
78+ newFormats [ index ] = targetFormats . concat (
79+ ( newFormats [ index ] || [ ] ) . slice ( targetFormats . length - 1 )
80+ ) ;
81+ } else {
82+ const targetFormats = formats [ previousLineIndex ] || [ ] ;
7283 const lastformat = targetFormats [ targetFormats . length - 1 ] || rootFormat ;
7384
7485 newFormats [ index ] = targetFormats . concat (
7586 [ lastformat ] ,
7687 ( newFormats [ index ] || [ ] ) . slice ( targetFormats . length )
7788 ) ;
78- } else {
79- newFormats [ index ] = targetFormats . concat (
80- ( newFormats [ index ] || [ ] ) . slice ( targetFormats . length - 1 )
81- ) ;
8289 }
8390 }
8491
0 commit comments