1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-31 10:51:44 +02:00

fix pasting plain text, fixes #586 fixes #795 (#1059)

This commit is contained in:
Ian Storm Taylor
2017-09-06 11:54:33 -07:00
committed by GitHub
parent 2632c82228
commit bdb8234b8d
3 changed files with 32 additions and 29 deletions

View File

@@ -117,13 +117,14 @@ Changes.insertFragment = (change, fragment) => {
let { state } = change let { state } = change
let { document, selection } = state let { document, selection } = state
const { startText, endText } = state const { startText, endText, startInline } = state
const lastText = fragment.getLastText() const lastText = fragment.getLastText()
const lastInline = fragment.getClosestInline(lastText.key) const lastInline = fragment.getClosestInline(lastText.key)
const keys = document.getTexts().map(text => text.key) const keys = document.getTexts().map(text => text.key)
const isAppending = ( const isAppending = (
selection.hasEdgeAtEndOf(endText) || !startInline ||
selection.hasEdgeAtStartOf(startText) selection.hasEdgeAtStartOf(startText) ||
selection.hasEdgeAtEndOf(endText)
) )
change.insertFragmentAtRange(selection, fragment) change.insertFragmentAtRange(selection, fragment)

View File

@@ -1,13 +1,14 @@
import Base64 from '../serializers/base-64' import Base64 from '../serializers/base-64'
import Content from '../components/content'
import Block from '../models/block' import Block from '../models/block'
import Character from '../models/character' import Character from '../models/character'
import Inline from '../models/inline' import Content from '../components/content'
import Debug from 'debug' import Debug from 'debug'
import getPoint from '../utils/get-point' import Inline from '../models/inline'
import Plain from '../serializers/plain'
import Placeholder from '../components/placeholder' import Placeholder from '../components/placeholder'
import React from 'react' import React from 'react'
import getPoint from '../utils/get-point'
import getWindow from 'get-window' import getWindow from 'get-window'
import findDOMNode from '../utils/find-dom-node' import findDOMNode from '../utils/find-dom-node'
import { IS_CHROME, IS_MAC, IS_SAFARI } from '../constants/environment' import { IS_CHROME, IS_MAC, IS_SAFARI } from '../constants/environment'
@@ -840,10 +841,16 @@ function Plugin(options = {}) {
function onPasteText(e, data, change) { function onPasteText(e, data, change) {
debug('onPasteText', { data }) debug('onPasteText', { data })
data.text.split('\n').forEach((line, i) => {
if (i > 0) change.splitBlock() const { state } = change
change.insertText(line) const { document, selection, startBlock } = state
}) if (startBlock.isVoid) return
const { text } = data
const defaultBlock = { type: startBlock.type, data: startBlock.data }
const defaultMarks = document.getMarksAtRange(selection.collapseToStart())
const fragment = Plain.deserialize(text, { defaultBlock, defaultMarks }).document
change.insertFragment(fragment)
} }
/** /**

View File

@@ -7,25 +7,32 @@ import Raw from '../serializers/raw'
* @param {String} string * @param {String} string
* @param {Object} options * @param {Object} options
* @property {Boolean} toRaw * @property {Boolean} toRaw
* @property {String|Object} defaultBlock
* @property {Array} defaultMarks
* @return {State} * @return {State}
*/ */
function deserialize(string, options = {}) { function deserialize(string, options = {}) {
const {
defaultBlock = { type: 'line' },
defaultMarks = [],
} = options
const raw = { const raw = {
kind: 'state', kind: 'state',
document: { document: {
kind: 'document', kind: 'document',
nodes: string.split('\n').map((line) => { nodes: string.split('\n').map((line) => {
return { return {
...defaultBlock,
kind: 'block', kind: 'block',
type: 'line',
nodes: [ nodes: [
{ {
kind: 'text', kind: 'text',
ranges: [ ranges: [
{ {
text: line, text: line,
marks: [], marks: defaultMarks,
} }
] ]
} }
@@ -38,21 +45,6 @@ function deserialize(string, options = {}) {
return options.toRaw ? raw : Raw.deserialize(raw) return options.toRaw ? raw : Raw.deserialize(raw)
} }
/**
* Checks if the block has other blocks nested within
* @param {Node} node
* @return {Boolean}
*/
function hasNestedBlocks(node) {
return node &&
node.nodes &&
node.nodes.first() &&
node.nodes.first().kind &&
node.nodes.first().kind == 'block'
}
/** /**
* Serialize a `state` to plain text. * Serialize a `state` to plain text.
* *
@@ -75,9 +67,12 @@ function serialize(state) {
*/ */
function serializeNode(node) { function serializeNode(node) {
if (node.kind == 'document' || (node.kind == 'block' && hasNestedBlocks(node))) { if (
(node.kind == 'document') ||
(node.kind == 'block' && node.nodes.size > 0 && node.nodes.first().kind == 'block')
) {
return node.nodes return node.nodes
.map(childNode => serializeNode(childNode)) .map(n => serializeNode(n))
.filter(text => text != '') .filter(text => text != '')
.join('\n') .join('\n')
} else { } else {