diff --git a/packages/roosterjs-content-model-plugins/lib/autoFormat/list/getListTypeStyle.ts b/packages/roosterjs-content-model-plugins/lib/autoFormat/list/getListTypeStyle.ts index 81ffbc8f7a4..1439054d8d0 100644 --- a/packages/roosterjs-content-model-plugins/lib/autoFormat/list/getListTypeStyle.ts +++ b/packages/roosterjs-content-model-plugins/lib/autoFormat/list/getListTypeStyle.ts @@ -51,7 +51,7 @@ export function getListTypeStyle( if (bulletType && shouldSearchForBullet) { return { listType: 'UL', styleType: bulletType }; } else if (shouldSearchForNumbering) { - const previousList = getPreviousListLevel(model, paragraph); + const { previousList, hasSpaceBetween } = getPreviousListLevel(model, paragraph); const previousIndex = getPreviousListIndex(model, previousList); const previousListStyle = getPreviousListStyle(previousList); const numberingType = getNumberingListStyle( @@ -64,12 +64,13 @@ export function getListTypeStyle( return { listType: 'OL', styleType: numberingType, - index: - !isNewList(listMarker) && - previousListStyle === numberingType && - previousIndex - ? previousIndex + 1 - : undefined, + index: getIndex( + listMarker, + previousListStyle, + numberingType, + previousIndex, + hasSpaceBetween + ), }; } } @@ -77,6 +78,21 @@ export function getListTypeStyle( return undefined; } +const getIndex = ( + listMarker: string, + previousListStyle?: number, + numberingType?: number, + previousIndex?: number, + hasSpaceBetween?: boolean +) => { + const newList = isNewList(listMarker); + return previousListStyle && previousListStyle !== numberingType && newList + ? 1 + : !newList && previousListStyle === numberingType && hasSpaceBetween && previousIndex + ? previousIndex + 1 + : undefined; +}; + const getPreviousListIndex = ( model: ReadonlyContentModelDocument, previousListItem?: ReadonlyContentModelListItem @@ -93,7 +109,8 @@ const getPreviousListLevel = ( ['ListItem'], ['TableCell'] )[0]; - let listItem: ContentModelListItem | undefined = undefined; + let previousList: ContentModelListItem | undefined = undefined; + let hasSpaceBetween = false; if (blocks) { const listBlockIndex = blocks.parent.blocks.indexOf(paragraph); @@ -101,14 +118,16 @@ const getPreviousListLevel = ( for (let i = listBlockIndex - 1; i > -1; i--) { const item = blocks.parent.blocks[i]; if (isBlockGroupOfType(item, 'ListItem')) { - listItem = item; + previousList = item; break; + } else { + hasSpaceBetween = listBlockIndex > 0 ? true : false; } } } } - return listItem; + return { previousList, hasSpaceBetween }; }; const getPreviousListStyle = (list?: ContentModelListItem) => { diff --git a/packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts b/packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts index a3d707c1f7a..08686fbe122 100644 --- a/packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts +++ b/packages/roosterjs-content-model-plugins/lib/autoFormat/list/keyboardListTrigger.ts @@ -44,7 +44,7 @@ const triggerList = ( ) => { setListType(model, listType); const isOrderedList = listType == 'OL'; - if (index && index > 1 && isOrderedList) { + if (index && index > 0 && isOrderedList) { setModelListStartNumber(model, index); } setModelListStyle( diff --git a/packages/roosterjs-content-model-plugins/test/autoFormat/list/getListTypeStyleTest.ts b/packages/roosterjs-content-model-plugins/test/autoFormat/list/getListTypeStyleTest.ts index 7b75a84dadf..99531aa40e3 100644 --- a/packages/roosterjs-content-model-plugins/test/autoFormat/list/getListTypeStyleTest.ts +++ b/packages/roosterjs-content-model-plugins/test/autoFormat/list/getListTypeStyleTest.ts @@ -1032,4 +1032,328 @@ describe('getListTypeStyle', () => { runTest(model, undefined); }); + + it('should continue a list ', () => { + const model: ContentModelDocument = { + blockGroupType: 'Document', + blocks: [ + { + formatHolder: { + isSelected: false, + segmentType: 'SelectionMarker', + format: {}, + }, + levels: [ + { + listType: 'OL', + format: { + startNumberOverride: 1, + listStyleType: 'decimal', + }, + dataset: { + editingInfo: + '{"applyListStyleFromLevel":false,"orderedStyleType":1}', + }, + }, + ], + blockType: 'BlockGroup', + format: {}, + blockGroupType: 'ListItem', + blocks: [ + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + }, + { + formatHolder: { + isSelected: false, + segmentType: 'SelectionMarker', + format: {}, + }, + levels: [ + { + listType: 'OL', + format: { + listStyleType: 'decimal', + }, + dataset: { + editingInfo: + '{"applyListStyleFromLevel":false,"orderedStyleType":1}', + }, + }, + ], + blockType: 'BlockGroup', + format: {}, + blockGroupType: 'ListItem', + blocks: [ + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + }, + { + segments: [ + { + text: '3.', + segmentType: 'Text', + format: {}, + }, + { + isSelected: true, + segmentType: 'SelectionMarker', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + format: {}, + }; + runTest(model, { + listType: 'OL', + styleType: NumberingListType.Decimal, + index: undefined, + }); + }); + + it('should not continue a list - different styles ', () => { + const model: ContentModelDocument = { + blockGroupType: 'Document', + blocks: [ + { + formatHolder: { + isSelected: false, + segmentType: 'SelectionMarker', + format: {}, + }, + levels: [ + { + listType: 'OL', + format: { + startNumberOverride: 1, + listStyleType: 'decimal', + }, + dataset: { + editingInfo: + '{"applyListStyleFromLevel":false,"orderedStyleType":1}', + }, + }, + ], + blockType: 'BlockGroup', + format: {}, + blockGroupType: 'ListItem', + blocks: [ + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + }, + { + formatHolder: { + isSelected: false, + segmentType: 'SelectionMarker', + format: {}, + }, + levels: [ + { + listType: 'OL', + format: { + listStyleType: 'decimal', + }, + dataset: { + editingInfo: + '{"applyListStyleFromLevel":false,"orderedStyleType":1}', + }, + }, + ], + blockType: 'BlockGroup', + format: {}, + blockGroupType: 'ListItem', + blocks: [ + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + }, + { + segments: [ + { + text: 'a.', + segmentType: 'Text', + format: {}, + }, + { + isSelected: true, + segmentType: 'SelectionMarker', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + format: {}, + }; + runTest(model, { + listType: 'OL', + styleType: NumberingListType.LowerAlpha, + index: 1, + }); + }); + + it('should not continue a list - has space between list', () => { + const model: ContentModelDocument = { + blockGroupType: 'Document', + blocks: [ + { + formatHolder: { + isSelected: false, + segmentType: 'SelectionMarker', + format: {}, + }, + levels: [ + { + listType: 'OL', + format: { + startNumberOverride: 1, + listStyleType: 'decimal', + }, + dataset: { + editingInfo: + '{"applyListStyleFromLevel":false,"orderedStyleType":1}', + }, + }, + ], + blockType: 'BlockGroup', + format: {}, + blockGroupType: 'ListItem', + blocks: [ + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + }, + { + formatHolder: { + isSelected: false, + segmentType: 'SelectionMarker', + format: {}, + }, + levels: [ + { + listType: 'OL', + format: { + listStyleType: 'decimal', + }, + dataset: { + editingInfo: + '{"applyListStyleFromLevel":false,"orderedStyleType":1}', + }, + }, + ], + blockType: 'BlockGroup', + format: {}, + blockGroupType: 'ListItem', + blocks: [ + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + }, + { + segments: [ + { + text: 'test', + segmentType: 'Text', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + { + segments: [ + { + text: '3.', + segmentType: 'Text', + format: {}, + }, + { + isSelected: true, + segmentType: 'SelectionMarker', + format: {}, + }, + ], + segmentFormat: {}, + blockType: 'Paragraph', + format: {}, + }, + ], + format: {}, + }; + runTest(model, { + listType: 'OL', + styleType: NumberingListType.Decimal, + index: 3, + }); + }); });