Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #2699 If there is a list in a quote, clearFormat can't clear the quote #2797

Merged
merged 2 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export function clearModelFormat(
blocksToClear: [ReadonlyContentModelBlockGroup[], ShallowMutableContentModelBlock][],
segmentsToClear: ShallowMutableContentModelSegment[],
tablesToClear: [ContentModelTable, boolean][]
) {
): boolean {
let pendingStructureChange = false;

iterateSelections(
model,
(path, tableContext, block, segments) => {
Expand Down Expand Up @@ -75,14 +77,14 @@ export function clearModelFormat(
blocksToClear.length == 1
) {
segmentsToClear.splice(0, segmentsToClear.length, ...adjustWordSelection(model, marker));
clearListFormat(blocksToClear[0][0]);
pendingStructureChange = clearListFormat(blocksToClear[0][0]) || pendingStructureChange;
} else if (blocksToClear.length > 1 || blocksToClear.some(x => isWholeBlockSelected(x[1]))) {
// 2. If a full block or multiple blocks are selected, clear block format
for (let i = blocksToClear.length - 1; i >= 0; i--) {
const [path, block] = blocksToClear[i];

clearBlockFormat(path, block);
clearListFormat(path);
pendingStructureChange = clearListFormat(path) || pendingStructureChange;
clearContainerFormat(path, block);
}
}
Expand All @@ -92,6 +94,8 @@ export function clearModelFormat(

// 4. Clear format for table if any
createTablesFormat(tablesToClear);

return pendingStructureChange;
}

function createTablesFormat(tablesToClear: [ContentModelTable, boolean][]) {
Expand Down Expand Up @@ -191,6 +195,10 @@ function clearListFormat(path: ReadonlyContentModelBlockGroup[]) {

if (listItem) {
mutateBlock(listItem).levels = [];

return true;
} else {
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type {
ContentModelTable,
} from 'roosterjs-content-model-types';

const MAX_TRY = 3;

/**
* Clear format of selection
* @param editor The editor to clear format from
Expand All @@ -17,17 +19,27 @@ export function clearFormat(editor: IEditor) {

editor.formatContentModel(
model => {
const blocksToClear: [ContentModelBlockGroup[], ContentModelBlock][] = [];
const segmentsToClear: ContentModelSegment[] = [];
const tablesToClear: [ContentModelTable, boolean][] = [];
let changed = false;
let needtoRun = true;
let triedTimes = 0;

while (needtoRun && triedTimes++ < MAX_TRY) {
const blocksToClear: [ContentModelBlockGroup[], ContentModelBlock][] = [];
const segmentsToClear: ContentModelSegment[] = [];
const tablesToClear: [ContentModelTable, boolean][] = [];

needtoRun = clearModelFormat(model, blocksToClear, segmentsToClear, tablesToClear);

clearModelFormat(model, blocksToClear, segmentsToClear, tablesToClear);
normalizeContentModel(model);

normalizeContentModel(model);
changed =
changed ||
blocksToClear.length > 0 ||
segmentsToClear.length > 0 ||
tablesToClear.length > 0;
}

return (
blocksToClear.length > 0 || segmentsToClear.length > 0 || tablesToClear.length > 0
);
return changed;
},
{
apiName: 'clearFormat',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,13 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, [], [], []);
const result = clearModelFormat(model, [], [], []);

expect(model).toEqual({ blockGroupType: 'Document', blocks: [] });
expect(blocks).toEqual([]);
expect(segments).toEqual([]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model without selection', () => {
Expand All @@ -122,7 +123,7 @@ describe('clearModelFormat', () => {
para.segments.push(text);
model.blocks.push(para);

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand All @@ -144,6 +145,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([]);
expect(segments).toEqual([]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with text selection', () => {
Expand All @@ -161,7 +163,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand All @@ -188,6 +190,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[model], para]]);
expect(segments).toEqual([text2]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with link', () => {
Expand All @@ -211,7 +214,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -239,6 +242,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[model], para]]);
expect(segments).toEqual([text1]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with code', () => {
Expand All @@ -260,7 +264,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand All @@ -282,6 +286,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[model], para]]);
expect(segments).toEqual([text1]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with text selection in whole paragraph', () => {
Expand All @@ -300,7 +305,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -328,6 +333,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[model], para]]);
expect(segments).toEqual([text1, text2]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with collapsed selection', () => {
Expand All @@ -344,7 +350,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -375,6 +381,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[model], para]]);
expect(segments).toEqual([marker]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with collapsed selection inside word', () => {
Expand All @@ -392,7 +399,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -447,6 +454,7 @@ describe('clearModelFormat', () => {
text3,
]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with collapsed selection under list', () => {
Expand All @@ -463,7 +471,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -499,6 +507,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[list, model], para]]);
expect(segments).toEqual([marker]);
expect(tables).toEqual([]);
expect(result).toBeTrue();
});

it('Model with divider selection', () => {
Expand All @@ -516,7 +525,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand All @@ -540,6 +549,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[model], divider]]);
expect(segments).toEqual([]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with selection under list', () => {
Expand All @@ -558,7 +568,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -600,6 +610,7 @@ describe('clearModelFormat', () => {
},
]);
expect(tables).toEqual([]);
expect(result).toBeTrue();
});

it('Model with selection under list, has defaultSegmentFormat', () => {
Expand All @@ -620,7 +631,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -662,6 +673,7 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([[[list, model], para]]);
expect(segments).toEqual([text]);
expect(tables).toEqual([]);
expect(result).toBeTrue();
});

it('Model with selection under quote', () => {
Expand All @@ -688,7 +700,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -774,6 +786,7 @@ describe('clearModelFormat', () => {
]);
expect(segments).toEqual([text3, text4]);
expect(tables).toEqual([]);
expect(result).toBeFalse();
});

it('Model with selection under table', () => {
Expand All @@ -796,7 +809,7 @@ describe('clearModelFormat', () => {
const segments: any[] = [];
const tables: any[] = [];

clearModelFormat(model, blocks, segments, tables);
const result = clearModelFormat(model, blocks, segments, tables);

expect(model).toEqual({
blockGroupType: 'Document',
Expand Down Expand Up @@ -855,5 +868,6 @@ describe('clearModelFormat', () => {
expect(blocks).toEqual([]);
expect(segments).toEqual([]);
expect(tables).toEqual([[table, true]]);
expect(result).toBeFalse();
});
});
Loading
Loading