芝麻web文件管理V1.00
编辑当前文件:/home/freeclou/app.optimyar.com/backend/node_modules/draft-js/lib/editOnBeforeInput.js
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * * @emails oncall+draft_js */ 'use strict'; var DraftModifier = require("./DraftModifier"); var EditorState = require("./EditorState"); var UserAgent = require("fbjs/lib/UserAgent"); var getEntityKeyForSelection = require("./getEntityKeyForSelection"); var isEventHandled = require("./isEventHandled"); var isSelectionAtLeafStart = require("./isSelectionAtLeafStart"); var nullthrows = require("fbjs/lib/nullthrows"); var setImmediate = require("fbjs/lib/setImmediate"); // When nothing is focused, Firefox regards two characters, `'` and `/`, as // commands that should open and focus the "quickfind" search bar. This should // *never* happen while a contenteditable is focused, but as of v28, it // sometimes does, even when the keypress event target is the contenteditable. // This breaks the input. Special case these characters to ensure that when // they are typed, we prevent default on the event to make sure not to // trigger quickfind. var FF_QUICKFIND_CHAR = "'"; var FF_QUICKFIND_LINK_CHAR = '/'; var isFirefox = UserAgent.isBrowser('Firefox'); function mustPreventDefaultForCharacter(character) { return isFirefox && (character == FF_QUICKFIND_CHAR || character == FF_QUICKFIND_LINK_CHAR); } /** * Replace the current selection with the specified text string, with the * inline style and entity key applied to the newly inserted text. */ function replaceText(editorState, text, inlineStyle, entityKey, forceSelection) { var contentState = DraftModifier.replaceText(editorState.getCurrentContent(), editorState.getSelection(), text, inlineStyle, entityKey); return EditorState.push(editorState, contentState, 'insert-characters', forceSelection); } /** * When `onBeforeInput` executes, the browser is attempting to insert a * character into the editor. Apply this character data to the document, * allowing native insertion if possible. * * Native insertion is encouraged in order to limit re-rendering and to * preserve spellcheck highlighting, which disappears or flashes if re-render * occurs on the relevant text nodes. */ function editOnBeforeInput(editor, e) { if (editor._pendingStateFromBeforeInput !== undefined) { editor.update(editor._pendingStateFromBeforeInput); editor._pendingStateFromBeforeInput = undefined; } var editorState = editor._latestEditorState; var chars = e.data; // In some cases (ex: IE ideographic space insertion) no character data // is provided. There's nothing to do when this happens. if (!chars) { return; } // Allow the top-level component to handle the insertion manually. This is // useful when triggering interesting behaviors for a character insertion, // Simple examples: replacing a raw text ':)' with a smile emoji or image // decorator, or setting a block to be a list item after typing '- ' at the // start of the block. if (editor.props.handleBeforeInput && isEventHandled(editor.props.handleBeforeInput(chars, editorState, e.timeStamp))) { e.preventDefault(); return; } // If selection is collapsed, conditionally allow native behavior. This // reduces re-renders and preserves spellcheck highlighting. If the selection // is not collapsed, we will re-render. var selection = editorState.getSelection(); var selectionStart = selection.getStartOffset(); var anchorKey = selection.getAnchorKey(); if (!selection.isCollapsed()) { e.preventDefault(); editor.update(replaceText(editorState, chars, editorState.getCurrentInlineStyle(), getEntityKeyForSelection(editorState.getCurrentContent(), editorState.getSelection()), true)); return; } var newEditorState = replaceText(editorState, chars, editorState.getCurrentInlineStyle(), getEntityKeyForSelection(editorState.getCurrentContent(), editorState.getSelection()), false); // Bunch of different cases follow where we need to prevent native insertion. var mustPreventNative = false; if (!mustPreventNative) { // Browsers tend to insert text in weird places in the DOM when typing at // the start of a leaf, so we'll handle it ourselves. mustPreventNative = isSelectionAtLeafStart(editor._latestCommittedEditorState); } if (!mustPreventNative) { // Let's say we have a decorator that highlights hashtags. In many cases // we need to prevent native behavior and rerender ourselves -- // particularly, any case *except* where the inserted characters end up // anywhere except exactly where you put them. // // Using [] to denote a decorated leaf, some examples: // // 1. 'hi #' and append 'f' // desired rendering: 'hi [#f]' // native rendering would be: 'hi #f' (incorrect) // // 2. 'x [#foo]' and insert '#' before 'f' // desired rendering: 'x #[#foo]' // native rendering would be: 'x [##foo]' (incorrect) // // 3. '[#foobar]' and insert ' ' between 'foo' and 'bar' // desired rendering: '[#foo] bar' // native rendering would be: '[#foo bar]' (incorrect) // // 4. '[#foo]' and delete '#' [won't use this beforeinput codepath though] // desired rendering: 'foo' // native rendering would be: '[foo]' (incorrect) // // 5. '[#foo]' and append 'b' // desired rendering: '[#foob]' // native rendering would be: '[#foob]' // (native insertion here would be ok for decorators like simple spans, // but not more complex decorators. To be safe, we need to prevent it.) // // It is safe to allow native insertion if and only if the full list of // decorator ranges matches what we expect native insertion to give, and // the range lengths have not changed. We don't need to compare the content // because the only possible mutation to consider here is inserting plain // text and decorators can't affect text content. var oldBlockTree = editorState.getBlockTree(anchorKey); var newBlockTree = newEditorState.getBlockTree(anchorKey); mustPreventNative = oldBlockTree.size !== newBlockTree.size || oldBlockTree.zip(newBlockTree).some(function (_ref) { var oldLeafSet = _ref[0], newLeafSet = _ref[1]; // selectionStart is guaranteed to be selectionEnd here var oldStart = oldLeafSet.get('start'); var adjustedStart = oldStart + (oldStart >= selectionStart ? chars.length : 0); var oldEnd = oldLeafSet.get('end'); var adjustedEnd = oldEnd + (oldEnd >= selectionStart ? chars.length : 0); var newStart = newLeafSet.get('start'); var newEnd = newLeafSet.get('end'); var newDecoratorKey = newLeafSet.get('decoratorKey'); return (// Different decorators oldLeafSet.get('decoratorKey') !== newDecoratorKey || // Different number of inline styles oldLeafSet.get('leaves').size !== newLeafSet.get('leaves').size || // Different effective decorator position adjustedStart !== newStart || adjustedEnd !== newEnd || // Decorator already existed and its length changed newDecoratorKey != null && newEnd - newStart !== oldEnd - oldStart ); }); } if (!mustPreventNative) { mustPreventNative = mustPreventDefaultForCharacter(chars); } if (!mustPreventNative) { mustPreventNative = nullthrows(newEditorState.getDirectionMap()).get(anchorKey) !== nullthrows(editorState.getDirectionMap()).get(anchorKey); } if (mustPreventNative) { e.preventDefault(); newEditorState = EditorState.set(newEditorState, { forceSelection: true }); editor.update(newEditorState); return; } // We made it all the way! Let the browser do its thing and insert the char. newEditorState = EditorState.set(newEditorState, { nativelyRenderedContent: newEditorState.getCurrentContent() }); // The native event is allowed to occur. To allow user onChange handlers to // change the inserted text, we wait until the text is actually inserted // before we actually update our state. That way when we rerender, the text // we see in the DOM will already have been inserted properly. editor._pendingStateFromBeforeInput = newEditorState; setImmediate(function () { if (editor._pendingStateFromBeforeInput !== undefined) { editor.update(editor._pendingStateFromBeforeInput); editor._pendingStateFromBeforeInput = undefined; } }); } module.exports = editOnBeforeInput;