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; } } |