diff --git a/packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleList.ts b/packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleList.ts index f524d3917cfd..90105c7401fc 100644 --- a/packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleList.ts +++ b/packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleList.ts @@ -43,6 +43,9 @@ export const handleList: ContentModelBlockHandler = ( itemLevel.format.listStyleType != stackLevel.format?.listStyleType) ) { break; + } else if (itemLevel.listType == 'UL') { + // Apply metadata to list level to make sure list style is correct after rendering + applyMetadata(itemLevel, context.metadataAppliers.listLevel, itemLevel.format, context); } if ( diff --git a/packages/roosterjs-content-model-dom/test/modelToDom/handlers/handleListTest.ts b/packages/roosterjs-content-model-dom/test/modelToDom/handlers/handleListTest.ts index 33fa3d696e0d..8e449af30cc2 100644 --- a/packages/roosterjs-content-model-dom/test/modelToDom/handlers/handleListTest.ts +++ b/packages/roosterjs-content-model-dom/test/modelToDom/handlers/handleListTest.ts @@ -1,3 +1,5 @@ +import * as applyFormat from '../../../lib/modelToDom/utils/applyFormat'; +import * as applyMetadata from '../../../lib/modelToDom/utils/applyMetadata'; import * as reuseCachedElement from '../../../lib/domUtils/reuseCachedElement'; import { BulletListType } from '../../../lib/constants/BulletListType'; import { ContentModelListItem, ModelToDomContext } from 'roosterjs-content-model-types'; @@ -612,6 +614,96 @@ describe('handleList handles metadata', () => { }); expect(listItem.levels[0].format.listStyleType).toBe('disc'); }); + + it('List style type should be changed by metadata when there is existing UL to reuse', () => { + const listItem: ContentModelListItem = { + blockType: 'BlockGroup', + blockGroupType: 'ListItem', + blocks: [ + { + blockType: 'Paragraph', + segments: [ + { + segmentType: 'Br', + format: {}, + }, + ], + format: {}, + }, + ], + levels: [ + { + listType: 'UL', + format: {}, + dataset: { + editingInfo: '{"applyListStyleFromLevel":true}', + }, + }, + ], + formatHolder: { + segmentType: 'SelectionMarker', + isSelected: false, + format: {}, + }, + format: {}, + }; + + context = createModelToDomContext(undefined, { + metadataAppliers: { + listLevel: listLevelMetadataApplier, + }, + }); + + const existingUL = document.createElement('ul'); + context.listFormat.nodeStack = [ + { + node: parent, + refNode: null, + }, + { + node: existingUL, + listType: 'UL', + dataset: { + editingInfo: '{"applyListStyleFromLevel":true}', + }, + format: {}, + refNode: null, + }, + ]; + + const applyFormatSpy = spyOn(applyFormat, 'applyFormat').and.callThrough(); + const applyMetadataSpy = spyOn(applyMetadata, 'applyMetadata').and.callThrough(); + + handleList(document, parent, listItem, context, null); + + expect(applyMetadataSpy).toHaveBeenCalledTimes(1); + expect(applyMetadataSpy).toHaveBeenCalledWith( + listItem.levels[0], + context.metadataAppliers.listLevel as any, + listItem.levels[0].format, + context + ); + expect(applyFormatSpy).not.toHaveBeenCalled(); + + expectHtml(parent.outerHTML, ['
']); + expect(context.listFormat).toEqual({ + threadItemCounts: [], + nodeStack: [ + { + node: parent, + refNode: null, + }, + { + node: existingUL, + listType: 'UL', + dataset: { editingInfo: '{"applyListStyleFromLevel":true}' }, + format: {}, + refNode: null, + }, + ], + }); + expect(listItem.levels[0].format.listStyleType).toBe('disc'); + }); }); describe('handleList with cache', () => {