mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-22 15:02:51 +02:00
initial plain text paste support
This commit is contained in:
@@ -19,6 +19,7 @@ class Content extends React.Component {
|
|||||||
onBeforeInput: React.PropTypes.func,
|
onBeforeInput: React.PropTypes.func,
|
||||||
onChange: React.PropTypes.func,
|
onChange: React.PropTypes.func,
|
||||||
onKeyDown: React.PropTypes.func,
|
onKeyDown: React.PropTypes.func,
|
||||||
|
onPaste: React.PropTypes.func,
|
||||||
onSelect: React.PropTypes.func,
|
onSelect: React.PropTypes.func,
|
||||||
renderMark: React.PropTypes.func.isRequired,
|
renderMark: React.PropTypes.func.isRequired,
|
||||||
renderNode: React.PropTypes.func.isRequired,
|
renderNode: React.PropTypes.func.isRequired,
|
||||||
@@ -51,13 +52,49 @@ class Content extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On key down, bubble up.
|
* On certain events, bubble up.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* @param {Event} e
|
||||||
|
*/
|
||||||
|
|
||||||
|
onEvent(name, e) {
|
||||||
|
this.props[name](e)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On paste, determine the type and bubble up.
|
||||||
*
|
*
|
||||||
* @param {Event} e
|
* @param {Event} e
|
||||||
*/
|
*/
|
||||||
|
|
||||||
onKeyDown(e) {
|
onPaste(e) {
|
||||||
this.props.onKeyDown(e)
|
e.preventDefault()
|
||||||
|
const data = e.clipboardData
|
||||||
|
const { types } = data
|
||||||
|
const paste = {}
|
||||||
|
|
||||||
|
// Handle files.
|
||||||
|
if (data.files.length != 0) {
|
||||||
|
paste.type = 'files'
|
||||||
|
paste.files = data.files
|
||||||
|
}
|
||||||
|
|
||||||
|
// Treat it as rich text if there is HTML content.
|
||||||
|
else if (types.includes('text/plain') && types.includes('text/html')) {
|
||||||
|
paste.type = 'html'
|
||||||
|
paste.text = data.getData('text/plain')
|
||||||
|
paste.html = data.getData('text/html')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Treat everything else as plain text.
|
||||||
|
else {
|
||||||
|
paste.type = 'text'
|
||||||
|
paste.text = data.getData('text/plain')
|
||||||
|
}
|
||||||
|
|
||||||
|
paste.data = data
|
||||||
|
this.props.onPaste(e, paste)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,16 +142,6 @@ class Content extends React.Component {
|
|||||||
this.onChange(state)
|
this.onChange(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* On before input, add the character to the state.
|
|
||||||
*
|
|
||||||
* @param {Event} e
|
|
||||||
*/
|
|
||||||
|
|
||||||
onBeforeInput(e) {
|
|
||||||
this.props.onBeforeInput(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the editor content.
|
* Render the editor content.
|
||||||
*
|
*
|
||||||
@@ -136,14 +163,12 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
contentEditable
|
contentEditable suppressContentEditableWarning
|
||||||
suppressContentEditableWarning
|
|
||||||
spellCheck={false}
|
|
||||||
data-type='content'
|
|
||||||
onKeyDown={e => this.onKeyDown(e)}
|
|
||||||
onSelect={e => this.onSelect(e)}
|
|
||||||
onBeforeInput={e => this.onBeforeInput(e)}
|
|
||||||
style={style}
|
style={style}
|
||||||
|
onSelect={e => this.onSelect(e)}
|
||||||
|
onPaste={e => this.onPaste(e)}
|
||||||
|
onKeyDown={e => this.onEvent('onKeyDown', e)}
|
||||||
|
onBeforeInput={e => this.onEvent('onBeforeInput', e)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -80,13 +80,13 @@ class Editor extends React.Component {
|
|||||||
* state if one of them chooses to.
|
* state if one of them chooses to.
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {Event} e
|
* @param {Mixed} ...args
|
||||||
*/
|
*/
|
||||||
|
|
||||||
onEvent(name, e) {
|
onEvent(name, ...args) {
|
||||||
for (const plugin of this.state.plugins) {
|
for (const plugin of this.state.plugins) {
|
||||||
if (!plugin[name]) continue
|
if (!plugin[name]) continue
|
||||||
const newState = plugin[name](e, this.props.state, this)
|
const newState = plugin[name](...args, this.props.state, this)
|
||||||
if (!newState) continue
|
if (!newState) continue
|
||||||
this.props.onChange(newState)
|
this.props.onChange(newState)
|
||||||
break
|
break
|
||||||
@@ -106,6 +106,7 @@ class Editor extends React.Component {
|
|||||||
onChange={state => this.onChange(state)}
|
onChange={state => this.onChange(state)}
|
||||||
renderMark={mark => this.renderMark(mark)}
|
renderMark={mark => this.renderMark(mark)}
|
||||||
renderNode={node => this.renderNode(node)}
|
renderNode={node => this.renderNode(node)}
|
||||||
|
onPaste={(e, paste) => this.onEvent('onPaste', e, paste)}
|
||||||
onBeforeInput={e => this.onEvent('onBeforeInput', e)}
|
onBeforeInput={e => this.onEvent('onBeforeInput', e)}
|
||||||
onKeyDown={e => this.onEvent('onKeyDown', e)}
|
onKeyDown={e => this.onEvent('onKeyDown', e)}
|
||||||
/>
|
/>
|
||||||
|
@@ -127,6 +127,39 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The core `onPaste` handler.
|
||||||
|
*
|
||||||
|
* @param {Event} e
|
||||||
|
* @param {Object} paste
|
||||||
|
* @param {State} state
|
||||||
|
* @param {Editor} editor
|
||||||
|
* @return {State or Null} newState
|
||||||
|
*/
|
||||||
|
|
||||||
|
onPaste(e, paste, state, editor) {
|
||||||
|
// Don't handle files in core.
|
||||||
|
if (paste.type == 'files') return
|
||||||
|
|
||||||
|
// If the paste type is html...
|
||||||
|
if (paste.type == 'html') {
|
||||||
|
// First, check for a match in the clipboard.
|
||||||
|
// Otherwise, check if we have a paste deserializer.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, just insert the plain text splitting at characters.
|
||||||
|
let transform = state.transform()
|
||||||
|
|
||||||
|
paste.text
|
||||||
|
.split('\n')
|
||||||
|
.forEach((block, i) => {
|
||||||
|
if (i > 0) transform = transform.splitBlock()
|
||||||
|
transform = transform.insertText(block)
|
||||||
|
})
|
||||||
|
|
||||||
|
return transform.apply()
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default `node` renderer.
|
* Default `node` renderer.
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user