From 5480a82415d011fd813d850243e9c43fe5772c62 Mon Sep 17 00:00:00 2001 From: Jiuqing Song Date: Fri, 13 Sep 2024 10:06:11 -0700 Subject: [PATCH] Fix #2755 (#2795) --- .../lib/modelApi/block/setModelIndentation.ts | 13 +- .../modelApi/block/setModelIndentationTest.ts | 299 +++++++++++++++++- 2 files changed, 309 insertions(+), 3 deletions(-) diff --git a/packages/roosterjs-content-model-api/lib/modelApi/block/setModelIndentation.ts b/packages/roosterjs-content-model-api/lib/modelApi/block/setModelIndentation.ts index 217a0d5f641..6a1626f3c07 100644 --- a/packages/roosterjs-content-model-api/lib/modelApi/block/setModelIndentation.ts +++ b/packages/roosterjs-content-model-api/lib/modelApi/block/setModelIndentation.ts @@ -66,10 +66,19 @@ export function setModelIndentation( //if block has only one level, there is not need to check if it is multilevel selection } else if (block.levels.length == 1 || !isMultilevelSelection(model, block, parent)) { if (isIndent) { - const lastLevel = block.levels[block.levels.length - 1]; + const threadIdx = thread.indexOf(block); + const previousItem = thread[threadIdx - 1]; + const nextItem = thread[threadIdx + 1]; + const levelLength = block.levels.length; + const lastLevel = block.levels[levelLength - 1]; const newLevel: ContentModelListLevel = createListLevel( lastLevel?.listType || 'UL', - lastLevel?.format + lastLevel?.format, + previousItem && previousItem.levels.length > levelLength + ? previousItem.levels[levelLength].dataset + : nextItem && nextItem.levels.length > levelLength + ? nextItem.levels[levelLength].dataset + : undefined ); updateListMetadata(newLevel, metadata => { diff --git a/packages/roosterjs-content-model-api/test/modelApi/block/setModelIndentationTest.ts b/packages/roosterjs-content-model-api/test/modelApi/block/setModelIndentationTest.ts index 765ca3526e6..6bf1e233806 100644 --- a/packages/roosterjs-content-model-api/test/modelApi/block/setModelIndentationTest.ts +++ b/packages/roosterjs-content-model-api/test/modelApi/block/setModelIndentationTest.ts @@ -1,5 +1,5 @@ import * as getListAnnounceData from '../../../lib/modelApi/list/getListAnnounceData'; -import { FormatContentModelContext } from 'roosterjs-content-model-types'; +import { ContentModelDocument, FormatContentModelContext } from 'roosterjs-content-model-types'; import { setModelIndentation } from '../../../lib/modelApi/block/setModelIndentation'; import { createContentModelDocument, @@ -899,6 +899,303 @@ describe('indent', () => { }); expect(getListAnnounceDataSpy).not.toHaveBeenCalled(); }); + + it('Indent and follow previous item style', () => { + const model: ContentModelDocument = { + blockGroupType: 'Document', + blocks: [ + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { format: {}, dataset: { a: 'c' }, listType: 'OL' }, + ], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + format: {}, + segments: [ + { segmentType: 'SelectionMarker', format: {}, isSelected: true }, + ], + }, + ], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + ], + }; + + setModelIndentation(model, 'indent'); + + expect(model).toEqual({ + blockGroupType: 'Document', + blocks: [ + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { format: {}, dataset: { a: 'c' }, listType: 'OL' }, + ], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + format: {}, + segments: [ + { segmentType: 'SelectionMarker', format: {}, isSelected: true }, + ], + }, + ], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { + format: {}, + dataset: { a: 'c', editingInfo: '{"applyListStyleFromLevel":true}' }, + listType: 'OL', + }, + ], + }, + ], + }); + }); + + it('Indent and follow next item style', () => { + const model: ContentModelDocument = { + blockGroupType: 'Document', + blocks: [ + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + format: {}, + segments: [ + { segmentType: 'SelectionMarker', format: {}, isSelected: true }, + ], + }, + ], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { format: {}, dataset: { a: 'c' }, listType: 'OL' }, + ], + }, + ], + }; + + setModelIndentation(model, 'indent'); + + expect(model).toEqual({ + blockGroupType: 'Document', + blocks: [ + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + format: {}, + segments: [ + { segmentType: 'SelectionMarker', format: {}, isSelected: true }, + ], + }, + ], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { + format: {}, + dataset: { a: 'c', editingInfo: '{"applyListStyleFromLevel":true}' }, + listType: 'OL', + }, + ], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { format: {}, dataset: { a: 'c' }, listType: 'OL' }, + ], + }, + ], + }); + }); + + it('Indent, no style to follow', () => { + const model: ContentModelDocument = { + blockGroupType: 'Document', + blocks: [ + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + format: {}, + segments: [ + { segmentType: 'SelectionMarker', format: {}, isSelected: true }, + ], + }, + ], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + ], + }; + + setModelIndentation(model, 'indent'); + + expect(model).toEqual({ + blockGroupType: 'Document', + blocks: [ + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [{ format: {}, dataset: { a: 'b' }, listType: 'OL' }], + }, + { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + format: {}, + segments: [ + { segmentType: 'SelectionMarker', format: {}, isSelected: true }, + ], + }, + ], + format: {}, + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + levels: [ + { format: {}, dataset: { a: 'b' }, listType: 'OL' }, + { + format: {}, + dataset: { editingInfo: '{"applyListStyleFromLevel":true}' }, + listType: 'OL', + }, + ], + }, + ], + }); + }); }); describe('outdent', () => {