Skip to content

Commit

Permalink
Skip same format from LI (#2683)
Browse files Browse the repository at this point in the history
* Skip same format from LI

* Add test
  • Loading branch information
JiuqingSong authored Jun 7, 2024
1 parent 3cab230 commit a0f32c6
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { applyFormat } from '../utils/applyFormat';
import { applyMetadata } from '../utils/applyMetadata';
import { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';
import { stackFormat } from '../utils/stackFormat';
import { unwrap } from '../../domUtils/unwrap';
import type {
ContentModelBlockHandler,
Expand Down Expand Up @@ -40,7 +41,9 @@ export const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (
// Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling
applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);

context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
stackFormat(context, listItem.formatHolder.format, () => {
context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
});
} else {
// There is no level for this list item, that means it should be moved out of the list
// For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together
Expand Down
53 changes: 52 additions & 1 deletion packages/roosterjs-content-model-dom/test/endToEndTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,58 @@ describe('End to end test for DOM => Model => DOM/TEXT', () => {
],
},
'1\r\n2',
'<ul style="margin-bottom: 0in;"><li style="font-family: Calibri, sans-serif; font-size: 11pt; color: black; margin-right: 0in; margin-left: 0in;"><span style="font-family: Calibri, sans-serif; font-size: 11pt; color: black;">1</span></li><li style="font-family: Calibri, sans-serif; font-size: 11pt; color: black; margin-right: 0in; margin-left: 0in;"><span style="font-family: Calibri, sans-serif; font-size: 11pt; color: black;">2</span></li></ul>'
'<ul style="margin-bottom: 0in;"><li style="font-family: Calibri, sans-serif; font-size: 11pt; color: black; margin-right: 0in; margin-left: 0in;">1</li><li style="font-family: Calibri, sans-serif; font-size: 11pt; color: black; margin-right: 0in; margin-left: 0in;">2</li></ul>'
);
});

it('list with partially same format in list item and segment', () => {
runTest(
'<div><ul><li style="font-family: Arial; font-size: 10pt; color: red;"><div><span style="font-size: 12pt; font-family: Arial; font-weight: bold">test</span></div></li></ul></div>',
{
blockGroupType: 'Document',
blocks: [
{
blockType: 'BlockGroup',
blockGroupType: 'ListItem',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'Text',
text: 'test',
format: {
fontFamily: 'Arial',
fontSize: '12pt',
textColor: 'red',
fontWeight: 'bold',
},
},
],
format: {},
segmentFormat: {
fontFamily: 'Arial',
fontSize: '12pt',
textColor: 'red',
},
},
],
levels: [{ listType: 'UL', format: {}, dataset: {} }],
formatHolder: {
segmentType: 'SelectionMarker',
isSelected: false,
format: {
fontFamily: 'Arial',
fontSize: '10pt',
textColor: 'red',
},
},
format: {},
},
],
},
'test',
'<ul><li style="font-family: Arial; font-size: 10pt; color: red;"><div style="font-size: 12pt;"><b>test</b></div></li></ul>'
);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as applyFormat from '../../../lib/modelToDom/utils/applyFormat';
import * as handleBlockGroupChildren from '../../../lib/modelToDom/handlers/handleBlockGroupChildren';
import * as handleList from '../../../lib/modelToDom/handlers/handleList';
import { createListItem } from '../../../lib/modelApi/creators/createListItem';
import { createListLevel } from '../../../lib/modelApi/creators/createListLevel';
import { createModelToDomContext } from '../../../lib/modelToDom/context/createModelToDomContext';
import { createParagraph } from '../../../lib/modelApi/creators/createParagraph';
import { handleList as originalHandleList } from '../../../lib/modelToDom/handlers/handleList';
import { createText } from '../../../lib';
import { handleListItem } from '../../../lib/modelToDom/handlers/handleListItem';
import {
ContentModelBlockGroup,
Expand All @@ -18,22 +20,22 @@ import {

describe('handleListItem without format handler', () => {
let context: ModelToDomContext;
let handleBlockGroupChildren: jasmine.Spy<ContentModelHandler<ContentModelBlockGroup>>;
let handleList: jasmine.Spy<ContentModelBlockHandler<ContentModelListItem>>;
let handleBlockGroupChildrenSpy: jasmine.Spy<ContentModelHandler<ContentModelBlockGroup>>;
let handleListSpy: jasmine.Spy<ContentModelBlockHandler<ContentModelListItem>>;
let listItemMetadataApplier: jasmine.Spy<ApplyMetadata<
ListMetadataFormat,
ContentModelListItemFormat
>>;

beforeEach(() => {
handleBlockGroupChildren = jasmine.createSpy('handleBlockGroupChildren');
handleList = jasmine.createSpy('handleList').and.callFake(originalHandleList);
handleBlockGroupChildrenSpy = spyOn(handleBlockGroupChildren, 'handleBlockGroupChildren');
handleListSpy = spyOn(handleList, 'handleList').and.callThrough();
listItemMetadataApplier = jasmine.createSpy('listItemMetadataApplier');

context = createModelToDomContext(undefined, {
modelHandlerOverride: {
blockGroupChildren: handleBlockGroupChildren,
list: handleList,
blockGroupChildren: handleBlockGroupChildrenSpy,
list: handleListSpy,
},
formatApplierOverride: {
listItemThread: null,
Expand Down Expand Up @@ -64,11 +66,11 @@ describe('handleListItem without format handler', () => {
},
],
});
expect(handleList).toHaveBeenCalledTimes(1);
expect(handleList).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(handleListSpy).toHaveBeenCalledTimes(1);
expect(handleListSpy).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(applyFormat.applyFormat).not.toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildren).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildren).toHaveBeenCalledWith(
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledWith(
document,
document.createElement('li'),
listItem,
Expand Down Expand Up @@ -109,8 +111,8 @@ describe('handleListItem without format handler', () => {
},
],
});
expect(handleList).toHaveBeenCalledTimes(1);
expect(handleList).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(handleListSpy).toHaveBeenCalledTimes(1);
expect(handleListSpy).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(applyFormat.applyFormat).toHaveBeenCalledTimes(3);
expect(applyFormat.applyFormat).toHaveBeenCalledWith(
parent.firstChild as HTMLElement,
Expand All @@ -131,8 +133,8 @@ describe('handleListItem without format handler', () => {
context
);
expect(listItemMetadataApplier).toHaveBeenCalledWith(null, listItem.format, context);
expect(handleBlockGroupChildren).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildren).toHaveBeenCalledWith(
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledWith(
document,
parent.firstChild as HTMLElement,
listItem,
Expand Down Expand Up @@ -172,8 +174,8 @@ describe('handleListItem without format handler', () => {
},
],
});
expect(handleList).toHaveBeenCalledTimes(1);
expect(handleList).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(handleListSpy).toHaveBeenCalledTimes(1);
expect(handleListSpy).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(applyFormat.applyFormat).toHaveBeenCalledTimes(3);
expect(applyFormat.applyFormat).toHaveBeenCalledWith(
parent.firstChild as HTMLElement,
Expand All @@ -194,8 +196,8 @@ describe('handleListItem without format handler', () => {
context
);
expect(listItemMetadataApplier).toHaveBeenCalledWith(null, listItem.format, context);
expect(handleBlockGroupChildren).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildren).toHaveBeenCalledWith(
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledWith(
document,
parent.firstChild as HTMLElement,
listItem,
Expand All @@ -213,11 +215,11 @@ describe('handleListItem without format handler', () => {
const result = handleListItem(document, parent, listItem, context, br);

expect(parent.outerHTML).toBe('<div><ul><li></li></ul><br></div>');
expect(handleList).toHaveBeenCalledTimes(1);
expect(handleList).toHaveBeenCalledWith(document, parent, listItem, context, br);
expect(handleListSpy).toHaveBeenCalledTimes(1);
expect(handleListSpy).toHaveBeenCalledWith(document, parent, listItem, context, br);
expect(applyFormat.applyFormat).toHaveBeenCalled();
expect(handleBlockGroupChildren).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildren).toHaveBeenCalledWith(
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledWith(
document,
parent.firstChild!.firstChild as HTMLElement,
listItem,
Expand All @@ -226,6 +228,80 @@ describe('handleListItem without format handler', () => {
expect(result).toBe(br);
});

it('UL with same format on list and segment', () => {
const listItem = createListItem([createListLevel('UL')], {
fontFamily: 'Arial',
fontSize: '10pt',
textColor: 'red',
});
const para = createParagraph();
const text = createText('test', {
fontFamily: 'Arial',
fontSize: '10pt',
textColor: 'red',
});

para.segments.push(text);
listItem.blocks.push(para);

handleBlockGroupChildrenSpy.and.callThrough();

const parent = document.createElement('div');
const result = handleListItem(document, parent, listItem, context, null);

expect(parent.outerHTML).toBe(
'<div><ul><li style="font-family: Arial; font-size: 10pt; color: red;"><div>test</div></li></ul></div>'
);
expect(handleListSpy).toHaveBeenCalledTimes(1);
expect(handleListSpy).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(applyFormat.applyFormat).toHaveBeenCalled();
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledWith(
document,
parent.firstChild!.firstChild as HTMLElement,
listItem,
context
);
expect(result).toBe(null);
});

it('UL with different format on list and segment', () => {
const listItem = createListItem([createListLevel('UL')], {
fontFamily: 'Arial',
fontSize: '10pt',
textColor: 'red',
});
const para = createParagraph();
const text = createText('test', {
fontFamily: 'Arial',
fontSize: '12pt',
textColor: 'green',
});

para.segments.push(text);
listItem.blocks.push(para);

handleBlockGroupChildrenSpy.and.callThrough();

const parent = document.createElement('div');
const result = handleListItem(document, parent, listItem, context, null);

expect(parent.outerHTML).toBe(
'<div><ul><li style="font-family: Arial; font-size: 10pt; color: red;"><div><span style="font-size: 12pt; color: green;">test</span></div></li></ul></div>'
);
expect(handleListSpy).toHaveBeenCalledTimes(1);
expect(handleListSpy).toHaveBeenCalledWith(document, parent, listItem, context, null);
expect(applyFormat.applyFormat).toHaveBeenCalled();
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledTimes(1);
expect(handleBlockGroupChildrenSpy).toHaveBeenCalledWith(
document,
parent.firstChild!.firstChild as HTMLElement,
listItem,
context
);
expect(result).toBe(null);
});

it('With onNodeCreated', () => {
const listLevel0 = createListLevel('OL');
const listItem: ContentModelListItem = {
Expand Down

0 comments on commit a0f32c6

Please sign in to comment.