function editOnPaste()

in src/component/handlers/edit/editOnPaste.js [35:222]


function editOnPaste(editor: DraftEditor, e: SyntheticClipboardEvent<>): void {
  e.preventDefault();
  const data = new DataTransfer(e.clipboardData);

  // Get files, unless this is likely to be a string the user wants inline.
  if (!data.isRichText()) {
    const files: Array<Blob> = (data.getFiles(): any);
    const defaultFileText = data.getText();
    if (files.length > 0) {
      // Allow customized paste handling for images, etc. Otherwise, fall
      // through to insert text contents into the editor.
      if (
        editor.props.handlePastedFiles &&
        isEventHandled(editor.props.handlePastedFiles(files))
      ) {
        return;
      }

      /* $FlowFixMe[incompatible-call] This comment suppresses an error found
       * DataTransfer was typed. getFiles() returns an array of <Files extends
       * Blob>, not Blob */
      getTextContentFromFiles(files, (/*string*/ fileText) => {
        fileText = fileText || defaultFileText;
        if (!fileText) {
          return;
        }

        const editorState = editor._latestEditorState;
        const blocks = splitTextIntoTextBlocks(fileText);
        const character = CharacterMetadata.create({
          style: editorState.getCurrentInlineStyle(),
          entity: getEntityKeyForSelection(
            editorState.getCurrentContent(),
            editorState.getSelection(),
          ),
        });
        const currentBlockType =
          RichTextEditorUtil.getCurrentBlockType(editorState);

        const text = DraftPasteProcessor.processText(
          blocks,
          character,
          currentBlockType,
        );
        const fragment = BlockMapBuilder.createFromArray(text);

        const withInsertedText = DraftModifier.replaceWithFragment(
          editorState.getCurrentContent(),
          editorState.getSelection(),
          fragment,
        );

        editor.update(
          EditorState.push(editorState, withInsertedText, 'insert-fragment'),
        );
      });

      return;
    }
  }

  let textBlocks: Array<string> = [];
  let text: string = (data.getText(): any);
  let html: string = (data.getHTML(): any);
  const editorState = editor._latestEditorState;

  if (editor.props.formatPastedText) {
    const {text: formattedText, html: formattedHtml} =
      editor.props.formatPastedText(text, html);
    text = formattedText;
    html = ((formattedHtml: any): string);
  }

  if (text) {
    textBlocks = splitTextIntoTextBlocks(text);
  }

  let handleInternalPaste: ?() => void = null;

  if (!editor.props.stripPastedStyles) {
    // If the text from the paste event is rich content that matches what we
    // already have on the internal clipboard, assume that we should just use
    // the clipboard fragment for the paste. This will allow us to preserve
    // styling and entities, if any are present. Note that newlines are
    // stripped during comparison -- this is because copy/paste within the
    // editor in Firefox and IE will not include empty lines. The resulting
    // paste will preserve the newlines correctly.
    const internalClipboard = editor.getClipboard();
    if (
      !editor.props.formatPastedText &&
      data.isRichText() &&
      internalClipboard
    ) {
      if (
        // If the editorKey is present in the pasted HTML, it should be safe to
        // assume this is an internal paste.
        html?.indexOf(editor.getEditorKey()) !== -1 ||
        // The copy may have been made within a single block, in which case the
        // editor key won't be part of the paste. In this case, just check
        // whether the pasted text matches the internal clipboard.
        (textBlocks.length === 1 &&
          internalClipboard.size === 1 &&
          internalClipboard.first().getText() === text)
      ) {
        handleInternalPaste = () =>
          editor.update(
            insertFragment(editor._latestEditorState, internalClipboard),
          );
      }
    } else if (
      internalClipboard &&
      data.types.includes('com.apple.webarchive') &&
      !data.types.includes('text/html') &&
      areTextBlocksAndClipboardEqual(textBlocks, internalClipboard)
    ) {
      // Safari does not properly store text/html in some cases.
      // Use the internalClipboard if present and equal to what is on
      // the clipboard. See https://bugs.webkit.org/show_bug.cgi?id=19893.
      handleInternalPaste = () =>
        editor.update(
          insertFragment(editor._latestEditorState, internalClipboard),
        );
    }

    if (
      editor.props.handlePastedText &&
      isEventHandled(
        editor.props.handlePastedText(
          text,
          html,
          editorState,
          handleInternalPaste != null,
        ),
      )
    ) {
      return;
    }

    if (handleInternalPaste != null) {
      handleInternalPaste();
      return;
    }

    // If there is html paste data, try to parse that.
    if (html) {
      const htmlFragment = DraftPasteProcessor.processHTML(
        html,
        editor.props.blockRenderMap,
      );
      if (htmlFragment) {
        const {contentBlocks, entityMap} = htmlFragment;
        if (contentBlocks) {
          const htmlMap = BlockMapBuilder.createFromArray(contentBlocks);
          editor.update(
            insertFragment(editor._latestEditorState, htmlMap, entityMap),
          );
          return;
        }
      }
    }

    // Otherwise, create a new fragment from our pasted text. Also
    // empty the internal clipboard, since it's no longer valid.
    editor.setClipboard(null);
  }

  if (textBlocks.length) {
    const character = CharacterMetadata.create({
      style: editorState.getCurrentInlineStyle(),
      entity: getEntityKeyForSelection(
        editorState.getCurrentContent(),
        editorState.getSelection(),
      ),
    });

    const currentBlockType =
      RichTextEditorUtil.getCurrentBlockType(editorState);

    const textFragment = DraftPasteProcessor.processText(
      textBlocks,
      character,
      currentBlockType,
    );

    const textMap = BlockMapBuilder.createFromArray(textFragment);
    editor.update(insertFragment(editor._latestEditorState, textMap));
  }
}