diff --git a/examples/code-highlighting/index.js b/examples/code-highlighting/index.js
index 90c014bb8..6c09e2830 100644
--- a/examples/code-highlighting/index.js
+++ b/examples/code-highlighting/index.js
@@ -11,7 +11,41 @@ import initialState from './state.json'
*/
const NODES = {
- code: props =>
{props.children}
+ code: (props) => {
+ const { attributes, children, editor, node } = props
+ const language = node.data.get('language')
+
+ function onChange(e) {
+ const state = editor.getState()
+ const next = state
+ .transform()
+ .setNodeByKey(node.key, {
+ data: {
+ language: e.target.value
+ }
+ })
+ .apply()
+ editor.onChange(next)
+ }
+
+ return (
+
+
+ {props.children}
+
+
+
+
+
+ )
+ }
}
/**
@@ -136,8 +170,9 @@ class CodeHighlighting extends React.Component {
if (block.type != 'code') return text.characters
let characters = text.characters.asMutable()
+ const language = block.data.get('language')
const string = text.text
- const grammar = Prism.languages.javascript
+ const grammar = Prism.languages[language]
const tokens = Prism.tokenize(string, grammar)
let offset = 0
diff --git a/examples/code-highlighting/state.json b/examples/code-highlighting/state.json
index 14ec76035..582d11868 100644
--- a/examples/code-highlighting/state.json
+++ b/examples/code-highlighting/state.json
@@ -13,6 +13,9 @@
{
"kind": "block",
"type": "code",
+ "data": {
+ "language": "js"
+ },
"nodes": [
{
"kind": "text",
diff --git a/lib/components/node.js b/lib/components/node.js
index bd1e8e445..ffd7e8147 100644
--- a/lib/components/node.js
+++ b/lib/components/node.js
@@ -4,7 +4,7 @@ import Debug from 'debug'
import React from 'react'
import ReactDOM from 'react-dom'
import TYPES from '../utils/types'
-import Text from './text'
+import Leaf from './leaf'
import Void from './void'
import scrollTo from '../utils/scroll-to'
@@ -31,6 +31,7 @@ class Node extends React.Component {
*/
static propTypes = {
+ block: React.PropTypes.object,
editor: React.PropTypes.object.isRequired,
node: React.PropTypes.object.isRequired,
renderDecorations: React.PropTypes.func.isRequired,
@@ -47,7 +48,7 @@ class Node extends React.Component {
static defaultProps = {
style: {}
- }
+ };
/**
* Constructor.
@@ -130,6 +131,17 @@ class Node extends React.Component {
return true
}
+ // For text nodes, which can have custom decorations, we need to check to
+ // see if the block has changed, which has caused the decorations to change.
+ if (
+ props.node.kind == 'text' &&
+ props.block != this.props.block
+ ) {
+ const nextRanges = props.node.getDecoratedRanges(props.block, props.renderDecorations)
+ const ranges = this.props.node.getDecoratedRanges(this.props.block, this.props.renderDecorations)
+ if (!ranges.equals(nextRanges)) return true
+ }
+
// Otherwise, don't update.
return false
}
@@ -216,10 +228,12 @@ class Node extends React.Component {
*/
renderNode = (child) => {
- const { editor, renderDecorations, renderMark, renderNode, state } = this.props
+ const { editor, node, renderDecorations, renderMark, renderNode, state } = this.props
+ const block = node.kind == 'block' ? node : this.props.block
return (
{
- const { node, editor, renderDecorations, renderMark, state } = this.props
+ const { node, block, renderDecorations } = this.props
+ const ranges = node.getDecoratedRanges(block, renderDecorations)
+ let offset = 0
+
+ const leaves = ranges.map((range, i, original) => {
+ const leaf = this.renderLeaf(ranges, range, i, offset)
+ offset += range.text.length
+ return leaf
+ })
+
return (
-
+ {leaves}
+
+ )
+ }
+
+ /**
+ * Render a single leaf node given a `range` and `offset`.
+ *
+ * @param {List} ranges
+ * @param {Range} range
+ * @param {Number} index
+ * @param {Number} offset
+ * @return {Element} leaf
+ */
+
+ renderLeaf = (ranges, range, index, offset) => {
+ const { node, renderMark, state } = this.props
+ const text = range.text
+ const marks = range.marks
+
+ return (
+
)
}
@@ -298,6 +345,8 @@ class Node extends React.Component {
/**
* Export.
+ *
+ * @type {Component}
*/
export default Node
diff --git a/lib/components/text.js b/lib/components/text.js
deleted file mode 100644
index 4175d145b..000000000
--- a/lib/components/text.js
+++ /dev/null
@@ -1,109 +0,0 @@
-
-import Leaf from './leaf'
-import React from 'react'
-import { List } from 'immutable'
-
-/**
- * Text.
- */
-
-class Text extends React.Component {
-
- /**
- * Properties.
- */
-
- static propTypes = {
- editor: React.PropTypes.object.isRequired,
- node: React.PropTypes.object.isRequired,
- renderDecorations: React.PropTypes.func.isRequired,
- renderMark: React.PropTypes.func.isRequired,
- state: React.PropTypes.object.isRequired
- };
-
- /**
- * Should the component update?
- *
- * @param {Object} props
- * @param {Object} state
- * @return {Boolean} shouldUpdate
- */
-
- shouldComponentUpdate(props, state) {
- return (
- props.node != this.props.node ||
- (props.state.isFocused && props.state.selection.hasEdgeIn(props.node))
- )
- }
-
- /**
- * Render.
- *
- * @return {Element} element
- */
-
- render() {
- const { node } = this.props
- return (
-
- {this.renderLeaves()}
-
- )
- }
-
- /**
- * Render the leaf nodes.
- *
- * @return {Array} leaves
- */
-
- renderLeaves() {
- const { node, state, renderDecorations } = this.props
- const block = state.document.getClosestBlock(node)
- const ranges = node.getDecoratedRanges(block, renderDecorations)
-
- return ranges.map((range, i, original) => {
- const previous = original.slice(0, i)
- const offset = previous.size
- ? previous.map(r => r.text).join('').length
- : 0
- return this.renderLeaf(ranges, range, i, offset)
- })
- }
-
- /**
- * Render a single leaf node given a `range` and `offset`.
- *
- * @param {List} ranges
- * @param {Range} range
- * @param {Number} index
- * @param {Number} offset
- * @return {Element} leaf
- */
-
- renderLeaf(ranges, range, index, offset) {
- const { node, renderMark, state } = this.props
- const text = range.text
- const marks = range.marks
-
- return (
-
- )
- }
-
-}
-
-/**
- * Export.
- */
-
-export default Text