Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 1x 1x 17x 17x 17x 9x 9x 1x 1x 7x 7x 7x 7x 3x 7x 7x 1x 25x 1x 17x 15x 15x 15x 15x 8x 8x 4x 4x 15x 4x | import {
mutateBlock,
normalizeContentModel,
setParagraphNotImplicit,
} from 'roosterjs-content-model-dom';
import type {
DeleteResult,
FormatContentModelContext,
IEditor,
ReadonlyContentModelBlockGroup,
ReadonlyContentModelDocument,
} from 'roosterjs-content-model-types';
/**
* @internal
* @return True means content is changed, so need to rewrite content model to editor. Otherwise false
*/
export function handleKeyboardEventResult(
editor: IEditor,
model: ReadonlyContentModelDocument,
rawEvent: KeyboardEvent,
result: DeleteResult,
context: FormatContentModelContext
): boolean {
context.skipUndoSnapshot = true;
context.clearModelCache = false;
switch (result) {
case 'notDeleted':
// We have not delete anything, we will let browser handle this event, so that current cached model may be invalid
context.clearModelCache = true;
// Return false here since we didn't do any change to Content Model, so no need to rewrite with Content Model
return false;
case 'nothingToDelete':
// We known there is nothing to delete, no need to let browser keep handling the event
rawEvent.preventDefault();
return false;
case 'range':
case 'singleChar':
// We have deleted what we need from content model, no need to let browser keep handling the event
rawEvent.preventDefault();
normalizeContentModel(model);
deleteEmptyBlockGroups(model);
if (result == 'range') {
// A range is about to be deleted, so add an undo snapshot immediately
context.skipUndoSnapshot = false;
}
// Trigger an event to let plugins know the content is about to be changed by Content Model keyboard editing.
// So plugins can do proper handling. e.g. UndoPlugin can decide whether take a snapshot before this change happens.
editor.triggerEvent('beforeKeyboardEditing', {
rawEvent,
});
return true;
}
}
/**
* @internal
*/
export function shouldDeleteWord(rawEvent: KeyboardEvent, isMac: boolean) {
return (
(isMac && rawEvent.altKey && !rawEvent.metaKey) ||
(!isMac && rawEvent.ctrlKey && !rawEvent.altKey)
);
}
/**
* @internal
*/
export function shouldDeleteAllSegmentsBefore(rawEvent: KeyboardEvent) {
return rawEvent.metaKey && !rawEvent.altKey;
}
function deleteEmptyBlockGroups(group: ReadonlyContentModelBlockGroup) {
let modified = false;
for (let i = group.blocks.length - 1; i >= 0; i--) {
const block = group.blocks[i];
if (block.blockType == 'BlockGroup') {
deleteEmptyBlockGroups(block);
if (block.blocks.length == 0) {
mutateBlock(group).blocks.splice(i, 1);
modified = true;
}
}
}
if (modified) {
group.blocks.forEach(setParagraphNotImplicit);
}
}
|