diff --git a/examples/rich-text/index.js b/examples/rich-text/index.js index 55a1ec590..4874a7f97 100644 --- a/examples/rich-text/index.js +++ b/examples/rich-text/index.js @@ -307,6 +307,7 @@ class RichText extends React.Component { renderMark={this.renderMark} onChange={this.onChange} onKeyDown={this.onKeyDown} + style={{}} /> ) diff --git a/lib/components/content.js b/lib/components/content.js index 892c89c77..6aed0ce16 100644 --- a/lib/components/content.js +++ b/lib/components/content.js @@ -1,5 +1,6 @@ import Base64 from '../serializers/base-64' +import Debug from 'debug' import Node from './node' import OffsetKey from '../utils/offset-key' import React from 'react' @@ -9,6 +10,14 @@ import includes from 'lodash/includes' import keycode from 'keycode' import { IS_FIREFOX, IS_MAC } from '../utils/environment' +/** + * Debug. + * + * @type {Function} + */ + +const debug = Debug('slate:content') + /** * Noop. * @@ -101,7 +110,7 @@ class Content extends React.Component { * While rendering, set the `isRendering` flag. * * @param {Object} props - * @param {Object} state] + * @param {Object} state */ componentWillUpdate = (props, state) => { @@ -112,7 +121,7 @@ class Content extends React.Component { * When finished rendering, move the `isRendering` flag on next tick. * * @param {Object} props - * @param {Object} state] + * @param {Object} state */ componentDidUpdate = (props, state) => { @@ -162,6 +171,8 @@ class Content extends React.Component { if (isNonEditable(e)) return const data = {} + + debug('onBeforeInput', data) this.props.onBeforeInput(e, data) } @@ -177,6 +188,8 @@ class Content extends React.Component { if (isNonEditable(e)) return const data = {} + + debug('onBlur', data) this.props.onBlur(e, data) } @@ -187,6 +200,7 @@ class Content extends React.Component { */ onChange = (state) => { + debug('onChange', state) this.props.onChange(state) } @@ -201,6 +215,8 @@ class Content extends React.Component { this.tmp.isComposing = true this.tmp.compositions++ + + debug('onCompositionStart') } /** @@ -224,6 +240,8 @@ class Content extends React.Component { if (this.tmp.compositions > count) return this.tmp.isComposing = false }) + + debug('onCompositionEnd') } /** @@ -244,6 +262,8 @@ class Content extends React.Component { const data = {} data.type = 'fragment' data.fragment = state.fragment + + debug('onCopy', data) this.props.onCopy(e, data) } @@ -266,6 +286,8 @@ class Content extends React.Component { const data = {} data.type = 'fragment' data.fragment = state.fragment + + debug('onCut', data) this.props.onCut(e, data) } @@ -280,6 +302,8 @@ class Content extends React.Component { this.tmp.isDragging = false this.tmp.isInternalDrag = null + + debug('onDragEnd') } /** @@ -303,6 +327,8 @@ class Content extends React.Component { if (this.tmp.isDragging) return this.tmp.isDragging = true this.tmp.isInternalDrag = false + + debug('onDragOver') } /** @@ -327,6 +353,8 @@ class Content extends React.Component { const { fragment } = state const encoded = Base64.serializeNode(fragment) data.setData(TYPES.FRAGMENT, encoded) + + debug('onDragStart') } /** @@ -413,6 +441,8 @@ class Content extends React.Component { data.target = target data.effect = dataTransfer.dropEffect + + debug('onDrop', data) this.props.onDrop(e, data) } @@ -424,8 +454,9 @@ class Content extends React.Component { */ onInput = (e) => { - if (this.isComposing) return + if (this.tmp.isComposing) return if (isNonEditable(e)) return + debug('onInput') let { state, renderDecorations } = this.props const { selection } = state @@ -483,6 +514,17 @@ class Content extends React.Component { const key = keycode(e.which) const data = {} + // When composing, these characters commit the composition but also move the + // selection before we're able to handle it, so prevent their default, + // selection-moving behavior. + if ( + this.tmp.isComposing && + (key == 'left' || key == 'right' || key == 'up' || key == 'down') + ) { + e.preventDefault() + return + } + // Add helpful properties for handling hotkeys to the data object. data.code = e.which data.key = key @@ -495,17 +537,6 @@ class Content extends React.Component { data.isShift = e.shiftKey data.isWord = IS_MAC ? e.altKey : e.ctrlKey - // When composing, these characters commit the composition but also move the - // selection before we're able to handle it, so prevent their default, - // selection-moving behavior. - if ( - this.tmp.isComposing && - (key == 'left' || key == 'right' || key == 'up' || key == 'down') - ) { - e.preventDefault() - return - } - // These key commands have native behavior in contenteditable elements which // will cause our state to be out of sync, so prevent them. if ( @@ -520,6 +551,7 @@ class Content extends React.Component { e.preventDefault() } + debug('onKeyDown', data) this.props.onKeyDown(e, data) } @@ -571,6 +603,7 @@ class Content extends React.Component { data.fragment = Base64.deserializeNode(encoded) } + debug('onPaste', data) this.props.onPaste(e, data) } @@ -631,6 +664,7 @@ class Content extends React.Component { .normalize(document) } + debug('onSelect', data) this.props.onSelect(e, data) } @@ -641,6 +675,8 @@ class Content extends React.Component { */ render = () => { + debug('render') + const { className, readOnly, state } = this.props const { document } = state const children = document.nodes diff --git a/lib/components/editor.js b/lib/components/editor.js index 429ee4c5d..a01520529 100644 --- a/lib/components/editor.js +++ b/lib/components/editor.js @@ -3,8 +3,15 @@ import Content from './content' import CorePlugin from '../plugins/core' import React from 'react' import State from '../models/state' +import Debug from 'debug' import typeOf from 'type-of' +/** + * Debug. + */ + +const debug = Debug('slate:editor') + /** * Noop. * @@ -197,6 +204,8 @@ class Editor extends React.Component { */ render = () => { + debug('render') + const handlers = {} for (const property of EVENT_HANDLERS) { diff --git a/lib/components/leaf.js b/lib/components/leaf.js index 83b03bb3c..885ec74de 100644 --- a/lib/components/leaf.js +++ b/lib/components/leaf.js @@ -1,16 +1,29 @@ +import Debug from 'debug' import OffsetKey from '../utils/offset-key' import React from 'react' import ReactDOM from 'react-dom' +/** + * Debugger. + * + * @type {Function} + */ + +const debug = Debug('slate:leaf') + /** * Leaf. + * + * @type {Component} */ class Leaf extends React.Component { /** - * Properties. + * Property types. + * + * @type {Object} */ static propTypes = { @@ -35,6 +48,17 @@ class Leaf extends React.Component { this.tmp.renders = 0 } + /** + * Debug. + * + * @param {String} message + * @param {Mixed} ...args + */ + + debug = (message, ...args) => { + debug(message, `${this.props.node.key}-${this.props.index}`, ...args) + } + /** * Should component update? * @@ -43,9 +67,6 @@ class Leaf extends React.Component { */ shouldComponentUpdate(props) { - const { index, node, state } = props - const { selection } = state - if ( props.index != this.props.index || props.marks != this.props.marks || @@ -55,9 +76,13 @@ class Leaf extends React.Component { return true } - if (state.isBlurred) return false + if (props.state.isBlurred) { + return false + } + + const { index, node, state } = props const { start, end } = OffsetKey.findBounds(index, props.ranges) - return selection.hasEdgeBetween(node, start, end) + return state.selection.hasEdgeBetween(node, start, end) } componentDidMount() { @@ -132,9 +157,13 @@ class Leaf extends React.Component { native.extend(endNode, endOffset) } } + + this.debug('updateSelection') } render() { + this.debug('render') + const { node, index } = this.props const offsetKey = OffsetKey.stringify({ key: node.key, diff --git a/lib/components/node.js b/lib/components/node.js index 80558f316..41238564b 100644 --- a/lib/components/node.js +++ b/lib/components/node.js @@ -1,9 +1,18 @@ import Base64 from '../serializers/base-64' +import Debug from 'debug' import React from 'react' import TYPES from '../utils/types' import Text from './text' +/** + * Debugger. + * + * @type {Function} + */ + +const debug = Debug('slate:node') + /** * Node. * @@ -25,6 +34,28 @@ class Node extends React.Component { style: {} } + /** + * Debug. + * + * @param {String} message + * @param {Mixed} ...args + */ + + debug = (message, ...args) => { + const { node } = this.props + const { key, kind, type } = node + let id = kind == 'text' ? `${key} (${kind})` : `${key} (${type})` + debug(message, `${id}`, ...args) + } + + /** + * Should the node update? + * + * @param {Object} props + * @param {Object} state + * @return {Boolean} + */ + shouldComponentUpdate = (props) => { return ( props.node != this.props.node || @@ -43,6 +74,8 @@ class Node extends React.Component { const encoded = Base64.serializeNode(node) const data = e.nativeEvent.dataTransfer data.setData(TYPES.NODE, encoded) + + this.debug('onDragStart', e) } /** @@ -52,6 +85,8 @@ class Node extends React.Component { */ render = () => { + this.debug('render') + const { node } = this.props return node.kind == 'text' ? this.renderText() diff --git a/package.json b/package.json index 09aea4e18..782df1c49 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "main": "./dist/index.js", "dependencies": { "cheerio": "^0.20.0", + "debug": "^2.2.0", "detect-browser": "^1.3.3", "direction": "^0.1.5", "esrever": "^0.2.0", @@ -27,20 +28,17 @@ "babel-cli": "^6.10.1", "babel-core": "^6.9.1", "babel-eslint": "^6.1.0", - "babel-polyfill": "^6.9.1", "babel-preset-es2015": "^6.9.0", "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "babelify": "^7.3.0", "browserify": "^13.0.1", "browserify-shim": "^3.8.12", - "component-type": "^1.2.1", "disc": "^1.3.2", "envify": "^3.4.1", "eslint": "^3.0.1", "eslint-plugin-import": "^1.10.2", "eslint-plugin-react": "^5.2.2", - "exorcist": "^0.4.0", "gh-pages": "^0.11.0", "http-server": "^0.9.0", "is-image": "^1.0.1", diff --git a/test/helpers/assert-json.js b/test/helpers/assert-json.js index 699b49eaa..4136cc49d 100644 --- a/test/helpers/assert-json.js +++ b/test/helpers/assert-json.js @@ -1,6 +1,6 @@ import assert from 'assert' -import type from 'component-type' +import type from 'type-of' /** * Assertion error.