diff --git a/docs/reference/Readme.md b/docs/reference/Readme.md
index 5c52cbd37..21ac63a6a 100644
--- a/docs/reference/Readme.md
+++ b/docs/reference/Readme.md
@@ -9,19 +9,19 @@ This is the full reference documentation for all of the pieces of Slate, broken
- **Models**
- [Block](./models/block.md)
- [Character](./models/character.md)
- - [Data](./data.md)
+ - [Data](./models/data.md)
- [Document](./models/document.md)
- [Inline](./models/inline.md)
- [Mark](./models/mark.md)
- [Node](./models/node.md)
- [Selection](./models/selection.md)
- [State](./models/state.md)
- - [Text](./text.md)
+ - [Text](./models/text.md)
- [Transform](./models/transform.md)
- **Serializers**
- - [Html](./html.md)
- - [Plain](./plain.md)
- - [Raw](./raw.md)
+ - [Html](./serializers/html.md)
+ - [Plain](./serializers/plain.md)
+ - [Raw](./serializers/raw.md)
- **Plugins**
- [Plugins](./plugins/plugins.md)
- [Core](./plugins/core.md)
diff --git a/examples/rich-text/index.js b/examples/rich-text/index.js
index f3a48e327..bc5703504 100644
--- a/examples/rich-text/index.js
+++ b/examples/rich-text/index.js
@@ -17,7 +17,7 @@ const DEFAULT_NODE = 'paragraph'
*/
const NODES = {
- 'block-quote': props =>
{props.children}
,
+ 'block-quote': (props) => {props.children}
,
'bulleted-list': props => ,
'heading-one': props => {props.children}
,
'heading-two': props => {props.children}
,
diff --git a/lib/models/node.js b/lib/models/node.js
index 2d27144eb..80f49260b 100644
--- a/lib/models/node.js
+++ b/lib/models/node.js
@@ -824,16 +824,40 @@ const Node = {
},
/**
- * Map all children nodes, updating them in their parents.
+ * Map all child nodes, updating them in their parents. This method is
+ * optimized to not return a new node if no changes are made.
+ *
+ * @param {Function} iterator
+ * @return {Node} node
+ */
+
+ mapChildren(iterator) {
+ let nodes = this.nodes
+
+ nodes.forEach((node, i) => {
+ let ret = iterator(node, i, this.nodes)
+ if (ret != node) nodes = nodes.set(ret.key, ret)
+ })
+
+ return this.merge({ nodes })
+ },
+
+ /**
+ * Map all descendant nodes, updating them in their parents. This method is
+ * optimized to not return a new node if no changes are made.
*
* @param {Function} iterator
* @return {Node} node
*/
mapDescendants(iterator) {
- const nodes = this.nodes.map((node, i, original) => {
- if (node.kind != 'text') node = node.mapDescendants(iterator)
- return iterator(node, i, original)
+ let nodes = this.nodes
+
+ nodes.forEach((node, i) => {
+ let ret = node
+ if (ret.kind != 'text') ret = ret.mapDescendants(iterator)
+ ret = iterator(ret, i, this.nodes)
+ if (ret != node) nodes = nodes.set(ret.key, ret)
})
return this.merge({ nodes })
@@ -952,12 +976,7 @@ const Node = {
return this.merge({ nodes })
}
- const nodes = this.nodes.map((node) => {
- return node.kind == 'text'
- ? node
- : node.removeDescendant(key)
- })
-
+ const nodes = this.mapChildren(n => n.kind == 'text' ? n : n.removeDescendant(key))
return this.merge({ nodes })
},
@@ -970,19 +989,7 @@ const Node = {
updateDescendant(node) {
this.assertHasDescendant(node)
-
- if (this.hasChild(node)) {
- const nodes = this.nodes.map(child => child.key == node.key ? node : child)
- return this.merge({ nodes })
- }
-
- const nodes = this.nodes.map((child) => {
- if (child.kind == 'text') return child
- if (!child.hasDescendant(node)) return child
- return child.updateDescendant(node)
- })
-
- return this.merge({ nodes })
+ return this.mapDescendants(d => d.key == node.key ? node : d)
}
}
diff --git a/lib/plugins/core.js b/lib/plugins/core.js
index 7b1d5a5e5..e7d5c2ef6 100644
--- a/lib/plugins/core.js
+++ b/lib/plugins/core.js
@@ -38,6 +38,13 @@ function Plugin(options = {}) {
state: React.PropTypes.object.isRequired
};
+ shouldComponentUpdate = (props, state) => {
+ return (
+ props.node != this.props.node ||
+ props.state.selection.hasEdgeIn(props.node)
+ )
+ }
+
render = () => {
const { attributes, children } = this.props
return (
@@ -80,6 +87,13 @@ function Plugin(options = {}) {
state: React.PropTypes.object.isRequired
};
+ shouldComponentUpdate = (props, state) => {
+ return (
+ props.node != this.props.node ||
+ props.state.selection.hasEdgeIn(props.node)
+ )
+ }
+
render = () => {
const { attributes, children } = this.props
return {children}