d2-ui
Version:
141 lines (117 loc) • 5.17 kB
JavaScript
/**
* 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;