1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-26 00:27:28 +02:00

fix add support for rendering components as marks

This commit is contained in:
Ian Storm Taylor
2016-07-29 11:20:00 -07:00
parent 4d58c0035c
commit fb97c50c4c
19 changed files with 147 additions and 65 deletions

View File

@@ -3,6 +3,7 @@ import Content from './content'
import CorePlugin from '../plugins/core'
import React from 'react'
import State from '../models/state'
import typeOf from 'type-of'
/**
* Noop.
@@ -242,21 +243,26 @@ class Editor extends React.Component {
*
* @param {Mark} mark
* @param {Set} marks
* @return {Element}
* @return {Component or Object or String}
*/
renderMark = (mark, marks) => {
for (const plugin of this.state.plugins) {
if (!plugin.renderMark) continue
let component = plugin.renderMark(mark, marks, this.state.state, this)
let ret = plugin.renderMark(mark, marks, this.state.state, this)
// plugin.renderMak can return a map of style
if (component && !(typeof component === 'function')) {
const style = component
component = (props => <span style={style}>{props.children}</span>)
// Handle React components that aren't stateless functions.
if (ret && ret.prototype && ret.prototype.isReactComponent) return ret
// Handle all other types...
switch (typeOf(ret)) {
case 'function':
return ret
case 'object':
return props => <span style={ret}>{props.children}</span>
case 'string':
return props => <span className={ret}>{props.children}</span>
}
if (component) return component
}
}

View File

@@ -3,22 +3,6 @@ import OffsetKey from '../utils/offset-key'
import React from 'react'
import ReactDOM from 'react-dom'
/**
* Find the deepest child (text node) of a DOM node
* @param {DOMNode} node
* @return {DOMNode}
*/
function findDeepestNode(node) {
let child = node.firstChild
if (child) {
return findDeepestNode(child)
}
return node
}
/**
* Leaf.
*/
@@ -168,7 +152,7 @@ class Leaf extends React.Component {
key={this.tmp.renders}
data-offset-key={offsetKey}
>
{this.renderWithMarks()}
{this.renderMarks()}
</span>
)
}
@@ -187,35 +171,31 @@ class Leaf extends React.Component {
return text
}
renderMark(inner, mark) {
const { node, index, renderMark, marks } = this.props
const offsetKey = OffsetKey.stringify({
key: node.key,
index
})
const MarkComponent = renderMark(mark, marks)
if (!MarkComponent) {
return inner
}
return (
<MarkComponent
mark={mark}
>
{inner}
</MarkComponent>
)
}
renderWithMarks() {
renderMarks() {
const { marks, renderMark } = this.props
const element = marks.reduce(this.renderMark, this.renderText(), this)
const text = this.renderText()
return element
return marks.reduce((children, mark) => {
const Component = renderMark(mark, marks)
if (!Component) return children
return <Component mark={mark} marks={marks}>{children}</Component>
}, text)
}
}
/**
* Find the deepest descendant of a DOM `element`.
*
* @param {Element} node
* @return {Element}
*/
function findDeepestNode(element) {
return element.firstChild
? findDeepestNode(element.firstChild)
: element
}
/**
* Export.
*/

View File

@@ -7,6 +7,14 @@ import ReactDOM from 'react-dom'
import keycode from 'keycode'
import { IS_FIREFOX } from '../utils/environment'
/**
* Noop.
*
* @type {Function}
*/
function noop() {}
/**
* Void.
*
@@ -156,7 +164,7 @@ class Void extends React.Component {
return (
<Leaf
renderMark={this.renderLeafMark}
renderMark={noop}
key={offsetKey}
state={state}
node={child}
@@ -168,16 +176,6 @@ class Void extends React.Component {
)
}
/**
* Render a fake leaf mark.
*
* @return {Object}
*/
renderLeafMark = (mark) => {
return
}
}
/**

View File

@@ -16,10 +16,12 @@ const BOLD_ITALIC = {
export function renderMark(mark, marks) {
if (
marks.size > 1 &&
marks.some(m => m.type == 'italic') &&
marks.some(m => m.type == 'bold')
marks.some(m => m.type == 'bold') &&
marks.some(m => m.type == 'italic')
) {
return mark.type == 'bold' ? BOLD_ITALIC : undefined
return mark.type == 'bold'
? BOLD_ITALIC
: null
}
if (mark.type == 'bold') return BOLD

View File

@@ -0,0 +1,12 @@
import React from 'react'
class Bold extends React.Component {
render() {
return <strong>{this.props.children}</strong>
}
}
export function renderMark(mark) {
if (mark.type == 'bold') return Bold
}

View File

@@ -0,0 +1,10 @@
<div contenteditable="true">
<div style="position:relative;">
<span>
<span>one</span>
<span><strong>two</strong></span>
<span>three</span>
</span>
</div>
</div>

View File

@@ -1,8 +1,8 @@
import React from 'react'
const BOLD = {
fontWeight: 'bold'
function BOLD(props) {
return <strong>{props.children}</strong>
}
export function renderMark(mark) {

View File

@@ -0,0 +1,12 @@
nodes:
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: one
- text: two
marks:
- type: bold
- text: three

View File

@@ -0,0 +1,10 @@
<div contenteditable="true">
<div style="position:relative;">
<span>
<span>one</span>
<span><strong>two</strong></span>
<span>three</span>
</span>
</div>
</div>

View File

@@ -5,7 +5,9 @@ const BOLD = {
fontWeight: 'bold'
}
const ITALIC = (props => <i>{props.children}</i>)
function ITALIC(props) {
return <i>{props.children}</i>
}
export function renderMark(mark, marks) {
if (mark.type == 'bold') return BOLD

View File

@@ -0,0 +1,10 @@
import React from 'react'
export function renderMark(mark) {
if (mark.type == 'bold') {
return {
fontWeight: 'bold'
}
}
}

View File

@@ -0,0 +1,12 @@
nodes:
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: one
- text: two
marks:
- type: bold
- text: three

View File

@@ -0,0 +1,6 @@
import React from 'react'
export function renderMark(mark) {
if (mark.type == 'bold') return 'bold'
}

View File

@@ -0,0 +1,12 @@
nodes:
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: one
- text: two
marks:
- type: bold
- text: three

View File

@@ -0,0 +1,10 @@
<div contenteditable="true">
<div style="position:relative;">
<span>
<span>one</span>
<span><span class="bold">two</span></span>
<span>three</span>
</span>
</div>
</div>