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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11x 11x 7x 7x 7x 7x 7x 6x 6x 6x 1x 7x 11x 1x 10x 8x 2x | import {
ChangeSource,
createText,
deleteSelection,
isModifierKey,
normalizeContentModel,
} from 'roosterjs-content-model-dom';
import type { DeleteSelectionStep, DOMSelection, IEditor } from 'roosterjs-content-model-types';
// Insert a ZeroWidthSpace(ZWS) segment with selection before selection marker
// so that later browser will replace this selection with inputted text and keep format
const ZWS = '\u200B';
const insertZWS: DeleteSelectionStep = context => {
Eif (context.deleteResult == 'range') {
const { marker, paragraph } = context.insertPoint;
const index = paragraph.segments.indexOf(marker);
Eif (index >= 0) {
const text = createText(ZWS, marker.format, marker.link, marker.code);
text.isSelected = true;
paragraph.segments.splice(index, 0, text);
}
}
};
/**
* @internal
*/
export function keyboardInput(editor: IEditor, rawEvent: KeyboardEvent) {
const selection = editor.getDOMSelection();
if (shouldInputWithContentModel(selection, rawEvent)) {
editor.takeSnapshot();
editor.formatContentModel(
(model, context) => {
const result = deleteSelection(model, [insertZWS], context);
// Skip undo snapshot here and add undo snapshot before the operation so that we don't add another undo snapshot in middle of this replace operation
context.skipUndoSnapshot = true;
if (result.deleteResult == 'range') {
// We have deleted something, next input should inherit the segment format from deleted content, so set pending format here
context.newPendingFormat = result.insertPoint?.marker.format;
normalizeContentModel(model);
// Do not preventDefault since we still want browser to handle the final input for now
return true;
} else {
return false;
}
},
{
scrollCaretIntoView: true,
rawEvent,
changeSource: ChangeSource.Keyboard,
getChangeData: () => rawEvent.which,
apiName: 'handleInputKey',
}
);
return true;
}
}
function shouldInputWithContentModel(selection: DOMSelection | null, rawEvent: KeyboardEvent) {
if (!selection) {
return false; // Nothing to delete
} else if (
!isModifierKey(rawEvent) &&
rawEvent.key &&
(rawEvent.key == 'Space' || rawEvent.key.length == 1)
) {
return selection.type != 'range' || !selection.range.collapsed;
} else {
return false;
}
}
|