diff --git a/lib/components/content.js b/lib/components/content.js
index a4b8cd83f..45dd2f076 100644
--- a/lib/components/content.js
+++ b/lib/components/content.js
@@ -19,6 +19,7 @@ class Content extends React.Component {
onBeforeInput: React.PropTypes.func,
onChange: React.PropTypes.func,
onKeyDown: React.PropTypes.func,
+ onPaste: React.PropTypes.func,
onSelect: React.PropTypes.func,
renderMark: 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
*/
- onKeyDown(e) {
- this.props.onKeyDown(e)
+ onPaste(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)
}
- /**
- * On before input, add the character to the state.
- *
- * @param {Event} e
- */
-
- onBeforeInput(e) {
- this.props.onBeforeInput(e)
- }
-
/**
* Render the editor content.
*
@@ -136,14 +163,12 @@ class Content extends React.Component {
return (
this.onKeyDown(e)}
- onSelect={e => this.onSelect(e)}
- onBeforeInput={e => this.onBeforeInput(e)}
+ contentEditable suppressContentEditableWarning
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}
diff --git a/lib/components/editor.js b/lib/components/editor.js
index ca5faddeb..6dc0cd859 100644
--- a/lib/components/editor.js
+++ b/lib/components/editor.js
@@ -80,13 +80,13 @@ class Editor extends React.Component {
* state if one of them chooses to.
*
* @param {String} name
- * @param {Event} e
+ * @param {Mixed} ...args
*/
- onEvent(name, e) {
+ onEvent(name, ...args) {
for (const plugin of this.state.plugins) {
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
this.props.onChange(newState)
break
@@ -106,6 +106,7 @@ class Editor extends React.Component {
onChange={state => this.onChange(state)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => this.renderNode(node)}
+ onPaste={(e, paste) => this.onEvent('onPaste', e, paste)}
onBeforeInput={e => this.onEvent('onBeforeInput', e)}
onKeyDown={e => this.onEvent('onKeyDown', e)}
/>
diff --git a/lib/plugins/core.js b/lib/plugins/core.js
index b8af26bdd..4e7ab22ee 100644
--- a/lib/plugins/core.js
+++ b/lib/plugins/core.js
@@ -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.
*