UNPKG

d2-ui

Version:
141 lines (117 loc) 5.17 kB
/** * Copyright (c) 2013-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule editOnPaste * */ /** * Paste content. */ 'use strict'; var BlockMapBuilder = require('./BlockMapBuilder'); var CharacterMetadata = require('./CharacterMetadata'); var DataTransfer = require('fbjs/lib/DataTransfer'); var DraftModifier = require('./DraftModifier'); var DraftPasteProcessor = require('./DraftPasteProcessor'); var EditorState = require('./EditorState'); var getEntityKeyForSelection = require('./getEntityKeyForSelection'); var getTextContentFromFiles = require('./getTextContentFromFiles'); var splitTextIntoTextBlocks = require('./splitTextIntoTextBlocks'); function editOnPaste(e) { var _this = this; e.preventDefault(); var data = new DataTransfer(e.clipboardData); // Get files, unless this is likely to be a string the user wants inline. if (!data.isRichText()) { var files = data.getFiles(); var 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 (this.props.handlePastedFiles && this.props.handlePastedFiles(files)) { return; } getTextContentFromFiles(files, function ( /*string*/fileText) { fileText = fileText || defaultFileText; if (!fileText) { return; } var editorState = _this.props.editorState; var blocks = splitTextIntoTextBlocks(fileText); var character = CharacterMetadata.create({ style: editorState.getCurrentInlineStyle(), entity: getEntityKeyForSelection(editorState.getCurrentContent(), editorState.getSelection()) }); var text = DraftPasteProcessor.processText(blocks, character); var fragment = BlockMapBuilder.createFromArray(text); var withInsertedText = DraftModifier.replaceWithFragment(editorState.getCurrentContent(), editorState.getSelection(), fragment); _this.update(EditorState.push(editorState, withInsertedText, 'insert-fragment')); }); return; } } var textBlocks = []; var text = data.getText(); var html = data.getHTML(); if (this.props.handlePastedText && this.props.handlePastedText(text, html)) { return; } if (text) { textBlocks = splitTextIntoTextBlocks(text); } if (!this.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. var internalClipboard = this.getClipboard(); if (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(this.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) { this.update(insertFragment(this.props.editorState, internalClipboard)); return; } } // If there is html paste data, try to parse that. if (html) { var htmlFragment = DraftPasteProcessor.processHTML(html, this.props.blockRenderMap); if (htmlFragment) { var htmlMap = BlockMapBuilder.createFromArray(htmlFragment); this.update(insertFragment(this.props.editorState, htmlMap)); return; } } // Otherwise, create a new fragment from our pasted text. Also // empty the internal clipboard, since it's no longer valid. this.setClipboard(null); } if (textBlocks) { var editorState = this.props.editorState; var character = CharacterMetadata.create({ style: editorState.getCurrentInlineStyle(), entity: getEntityKeyForSelection(editorState.getCurrentContent(), editorState.getSelection()) }); var textFragment = DraftPasteProcessor.processText(textBlocks, character); var textMap = BlockMapBuilder.createFromArray(textFragment); this.update(insertFragment(this.props.editorState, textMap)); } } function insertFragment(editorState, fragment) { var newContent = DraftModifier.replaceWithFragment(editorState.getCurrentContent(), editorState.getSelection(), fragment); return EditorState.push(editorState, newContent, 'insert-fragment'); } module.exports = editOnPaste;