Skip to content

Commit

Permalink
Improve backspace on list (#2555)
Browse files Browse the repository at this point in the history
  • Loading branch information
JiuqingSong authored Apr 3, 2024
1 parent 182ed16 commit 154d72d
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
import { getClosestAncestorBlockGroupIndex } from 'roosterjs-content-model-dom';
import type { DeleteSelectionStep } from 'roosterjs-content-model-types';
import type { DeleteSelectionStep, ContentModelListItem } from 'roosterjs-content-model-types';

/**
* @internal
*/
export const deleteList: DeleteSelectionStep = context => {
if (context.deleteResult != 'notDeleted') {
return;
}

const { paragraph, marker, path } = context.insertPoint;

if (context.deleteResult == 'nothingToDelete' || context.deleteResult == 'notDeleted') {
const index = getClosestAncestorBlockGroupIndex(path, ['ListItem', 'TableCell']);
const item = path[index];
if (
item &&
index >= 0 &&
paragraph.segments[0] == marker &&
item.blockGroupType == 'ListItem'
) {
item.levels = [];
if (paragraph.segments[0] == marker) {
const index = getClosestAncestorBlockGroupIndex<ContentModelListItem>(
path,
['ListItem'],
['TableCell', 'FormatContainer']
);
const item = path[index] as ContentModelListItem | undefined;
const lastLevel = item?.levels[item.levels.length - 1];

if (lastLevel && item?.blocks[0] == paragraph) {
if (lastLevel.format.displayForDummyItem == 'block') {
item.levels.pop();
} else {
lastLevel.format.displayForDummyItem = 'block';
}

context.deleteResult = 'range';
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const createNewListLevel = (listItem: ContentModelListItem) => {
{
...level.format,
startNumberOverride: undefined,
displayForDummyItem: undefined, // When ENTER, we should create a new regular list item, so force its dummy item display to undefined
},
level.dataset
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { deleteAllSegmentBefore } from './deleteSteps/deleteAllSegmentBefore';
import { deleteEmptyQuote } from './deleteSteps/deleteEmptyQuote';
import { deleteList } from './deleteSteps/deleteList';
import {
ChangeSource,
deleteSelection,
isModifierKey,
isNodeOfType,
} from 'roosterjs-content-model-dom';
import { deleteAllSegmentBefore } from './deleteSteps/deleteAllSegmentBefore';
import { deleteEmptyQuote } from './deleteSteps/deleteEmptyQuote';
import { deleteList } from './deleteSteps/deleteList';
import {
handleKeyboardEventResult,
shouldDeleteAllSegmentsBefore,
Expand Down Expand Up @@ -73,8 +73,8 @@ function getDeleteSteps(rawEvent: KeyboardEvent, isMac: boolean): (DeleteSelecti
return [
deleteAllSegmentBeforeStep,
deleteWordSelection,
isForward ? null : deleteList,
deleteCollapsedSelection,
deleteList,
deleteQuote,
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,81 @@ describe('deleteList', () => {
normalizeContentModel(model);
expect(result.deleteResult).toEqual('range');

expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
{
blockType: 'BlockGroup',
blockGroupType: 'ListItem',
format: {
listStyleType: '"1. "',
},
blocks: [
{
blockType: 'Paragraph',
format: {},
segments: [
{
segmentType: 'SelectionMarker',
format: {},
isSelected: true,
},
{
segmentType: 'Br',
format: {},
},
],
isImplicit: true,
},
],
levels: [
{
listType: 'OL',
format: {
displayForDummyItem: 'block',
},
dataset: {},
},
],
formatHolder: {
segmentType: 'SelectionMarker',
isSelected: false,
format: {},
},
},
],
});

const result2 = deleteSelection(model, [deleteList]);
normalizeContentModel(model);
expect(result2.deleteResult).toEqual('range');

expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
{
blockType: 'Paragraph',
format: {},
segments: [
{
segmentType: 'SelectionMarker',
format: {},
isSelected: true,
},
{
segmentType: 'Br',
format: {},
},
],
isImplicit: false,
},
],
});

const result3 = deleteSelection(model, [deleteList]);
normalizeContentModel(model);
expect(result3.deleteResult).toEqual('notDeleted');

expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
Expand Down Expand Up @@ -401,6 +476,89 @@ describe('deleteList', () => {
};
const result = deleteSelection(model, [deleteList]);
normalizeContentModel(model);

expect(result.deleteResult).toBe('range');
expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
{
blockType: 'Table',
rows: [
{
height: 22,
format: {},
cells: [
{
blockGroupType: 'TableCell',
blocks: [
{
blockType: 'BlockGroup',
blockGroupType: 'ListItem',
blocks: [
{
blockType: 'Paragraph',
segments: [
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
{
segmentType: 'Br',
format: {},
},
],
format: {},
isImplicit: false,
},
],
levels: [
{
listType: 'UL',
format: {
marginTop: '0px',
marginBottom: '0px',
listStyleType: 'disc',
displayForDummyItem: 'block',
},
dataset: {},
},
],
formatHolder: {
segmentType: 'SelectionMarker',
isSelected: false,
format: {},
},
format: {},
},
],
format: {},
spanLeft: false,
spanAbove: false,
isHeader: false,
dataset: {},
},
],
},
],
format: {
useBorderBox: true,
borderCollapse: true,
},
widths: [120],
dataset: {
editingInfo:
'{"topBorderColor":"#ABABAB","bottomBorderColor":"#ABABAB","verticalBorderColor":"#ABABAB","hasHeaderRow":false,"hasFirstColumn":false,"hasBandedRows":false,"hasBandedColumns":false,"bgColorEven":null,"bgColorOdd":"#ABABAB20","headerRowColor":"#ABABAB","tableBorderFormat":0,"verticalAlign":"top"}',
},
},
],
format: {},
});

const result2 = deleteSelection(model, [deleteList]);
normalizeContentModel(model);

expect(result2.deleteResult).toBe('range');
expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
Expand Down Expand Up @@ -453,7 +611,6 @@ describe('deleteList', () => {
],
format: {},
});
expect(result.deleteResult).toEqual('range');
});

it('delete list if the cursor is before text', () => {
Expand Down Expand Up @@ -507,6 +664,60 @@ describe('deleteList', () => {
const result = deleteSelection(model, [deleteList]);
normalizeContentModel(model);
expect(result.deleteResult).toEqual('range');
expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
{
blockType: 'BlockGroup',
blockGroupType: 'ListItem',
format: {
listStyleType: '"1. "',
},
blocks: [
{
blockType: 'Paragraph',
format: {},
segments: [
{
segmentType: 'SelectionMarker',
format: {},
isSelected: true,
},
{
segmentType: 'Text',
text: 'text',
format: {},
},
{
segmentType: 'Br',
format: {},
},
],
isImplicit: true,
},
],
levels: [
{
listType: 'OL',
format: {
displayForDummyItem: 'block',
},
dataset: {},
},
],
formatHolder: {
segmentType: 'SelectionMarker',
isSelected: false,
format: {},
},
},
],
});

const result2 = deleteSelection(model, [deleteList]);
normalizeContentModel(model);
expect(result2.deleteResult).toEqual('range');

expect(model).toEqual({
blockGroupType: 'Document',
blocks: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ describe('handleEnterOnList', () => {
marginBottom: '0px',
listStyleType: 'decimal',
startNumberOverride: undefined,
displayForDummyItem: undefined,
},
dataset: {
editingInfo: '{"orderedStyleType":1}',
Expand Down Expand Up @@ -436,6 +437,7 @@ describe('handleEnterOnList', () => {
marginBottom: '0px',
listStyleType: 'decimal',
startNumberOverride: undefined,
displayForDummyItem: undefined,
},
dataset: {
editingInfo: '{"orderedStyleType":1}',
Expand Down Expand Up @@ -817,6 +819,7 @@ describe('handleEnterOnList', () => {
marginTop: '0px',
marginBottom: '0px',
startNumberOverride: undefined,
displayForDummyItem: undefined,
},
dataset: {
editingInfo: '{"orderedStyleType":10}',
Expand Down Expand Up @@ -1898,6 +1901,7 @@ describe(' handleEnterOnList - keyboardInput', () => {
marginBottom: '0px',
listStyleType: 'decimal',
startNumberOverride: undefined,
displayForDummyItem: undefined,
},
dataset: {
editingInfo: '{"orderedStyleType":1}',
Expand Down
Loading

0 comments on commit 154d72d

Please sign in to comment.