1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-10 17:24:02 +02:00

cleanup renderers in examples, fixes #43

This commit is contained in:
Ian Storm Taylor
2016-07-06 14:42:59 -07:00
parent e9ed40dd7f
commit de4afd38b1
12 changed files with 240 additions and 338 deletions

View File

@@ -4,10 +4,29 @@ import React from 'react'
import keycode from 'keycode'
import state from './state.json'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
'block-quote': props => <blockquote>{props.children}</blockquote>,
'bulleted-list': props => <ul>{props.children}</ul>,
'heading-one': props => <h1>{props.children}</h1>,
'heading-two': props => <h2>{props.children}</h2>,
'heading-three': props => <h3>{props.children}</h3>,
'heading-four': props => <h4>{props.children}</h4>,
'heading-five': props => <h5>{props.children}</h5>,
'heading-six': props => <h6>{props.children}</h6>,
'list-item': props => <li>{props.children}</li>,
'paragraph': props => <p>{props.children}</p>
}
/**
* The auto-markdown example.
*
* @type {Component} AutoMarkdown
* @type {Component}
*/
class AutoMarkdown extends React.Component {
@@ -57,8 +76,7 @@ class AutoMarkdown extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => NODES[node.type]}
onKeyDown={(e, state) => this.onKeyDown(e, state)}
onChange={(state) => {
console.groupCollapsed('Change!')
@@ -73,48 +91,6 @@ class AutoMarkdown extends React.Component {
)
}
/**
* Render each of our custom `node` types.
*
* @param {Node} node
* @return {Component} component
*/
renderNode(node) {
switch (node.type) {
case 'block-quote': {
return (props) => <blockquote>{props.children}</blockquote>
}
case 'bulleted-list': {
return (props) => <ul>{props.children}</ul>
}
case 'heading-one': {
return (props) => <h1>{props.children}</h1>
}
case 'heading-two': {
return (props) => <h2>{props.children}</h2>
}
case 'heading-three': {
return (props) => <h3>{props.children}</h3>
}
case 'heading-four': {
return (props) => <h4>{props.children}</h4>
}
case 'heading-five': {
return (props) => <h5>{props.children}</h5>
}
case 'heading-six': {
return (props) => <h6>{props.children}</h6>
}
case 'list-item': {
return (props) => <li>{props.children}</li>
}
case 'paragraph': {
return (props) => <p>{props.children}</p>
}
}
}
/**
* On key down, check for our specific key shortcuts.
*

View File

@@ -6,7 +6,9 @@ import keycode from 'keycode'
import state from './state.json'
/**
* Node and mark renderers.
* Node renderers.
*
* @type {Object}
*/
const NODES = {
@@ -14,6 +16,12 @@ const NODES = {
paragraph: props => <p>{props.children}</p>
}
/**
* Mark renderers.
*
* @type {Object}
*/
const MARKS = {
'highlight-comment': {
opacity: '0.33'
@@ -29,7 +37,7 @@ const MARKS = {
/**
* Example.
*
* @type {Component} CodeHighlighting
* @type {Component}
*/
class CodeHighlighting extends React.Component {
@@ -56,8 +64,8 @@ class CodeHighlighting extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={(...args) => this.renderNode(...args)}
renderMark={(...args) => this.renderMark(...args)}
renderNode={node => NODES[node.type]}
renderMark={mark => MARKS[mark.type] || {}}
renderDecorations={(...args) => this.renderDecorations(...args)}
onKeyDown={(...args) => this.onKeyDown(...args)}
onChange={(state) => {
@@ -73,14 +81,6 @@ class CodeHighlighting extends React.Component {
)
}
renderNode(node) {
return NODES[node.type]
}
renderMark(mark) {
return MARKS[mark.type] || {}
}
renderDecorations(text, state, editor) {
let characters = text.characters
const { document } = state
@@ -88,7 +88,6 @@ class CodeHighlighting extends React.Component {
if (block.type != 'code') return characters
const string = text.text
console.log('render decorations:', string)
const grammar = Prism.languages.javascript
const tokens = Prism.tokenize(string, grammar)
let offset = 0
@@ -116,28 +115,6 @@ class CodeHighlighting extends React.Component {
return characters
}
// renderDecorations(text) {
// const { state } = this.state
// const { document } = state
// const block = document.getClosestBlock(text)
// if (block.type != 'code') return
// const string = text.text
// if (cache[string]) return cache[string]
// const grammar = Prism.languages.javascript
// const tokens = Prism.tokenize(string, grammar)
// const ranges = tokens.map((token) => {
// return typeof token == 'string'
// ? { text: token }
// : {
// text: token.content,
// marks: [{ type: token.type }]
// }
// })
// return cached[string] = ranges
// }
}
/**

View File

@@ -5,10 +5,44 @@ import React from 'react'
import position from 'selection-position'
import state from './state.json'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
paragraph: props => <p>{props.children}</p>
}
/**
* Mark renderers.
*
* @type {Object}
*/
const MARKS = {
bold: {
fontWeight: 'bold'
},
code: {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
},
italic: {
fontStyle: 'italic'
},
underlined: {
textDecoration: 'underline'
}
}
/**
* The rich text example.
*
* @type {Component} HoveringMenu
* @type {Component}
*/
class HoveringMenu extends React.Component {
@@ -101,8 +135,8 @@ class HoveringMenu extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => NODES[node.type]}
renderMark={mark => MARKS[mark.type]}
onChange={(state) => {
console.groupCollapsed('Change!')
console.log('Document:', state.document.toJS())
@@ -116,42 +150,6 @@ class HoveringMenu extends React.Component {
)
}
renderNode(node) {
switch (node.type) {
case 'paragraph': {
return (props) => <p>{props.children}</p>
}
}
}
renderMark(mark) {
switch (mark.type) {
case 'bold': {
return {
fontWeight: 'bold'
}
}
case 'code': {
return {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
}
}
case 'italic': {
return {
fontStyle: 'italic'
}
}
case 'underlined': {
return {
textDecoration: 'underline'
}
}
}
}
}
/**

View File

@@ -5,10 +5,27 @@ import ReactDOM from 'react-dom'
import state from './state.json'
import { Map } from 'immutable'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
paragraph: props => <p>{props.children}</p>,
image: (props) => {
const { node, state } = props
const { data } = node
const isActive = state.isFocused && state.blocks.includes(node)
const src = data.get('src')
return <img src={src} data-active={isActive} />
}
}
/**
* The images example.
*
* @type {Component} Images
* @type {Component}
*/
class Images extends React.Component {
@@ -112,7 +129,7 @@ class Images extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderNode={node => NODES[node.type]}
onChange={(state) => {
console.groupCollapsed('Change!')
console.log('Document:', state.document.toJS())
@@ -126,30 +143,6 @@ class Images extends React.Component {
)
}
/**
* Render our custom `node`.
*
* @param {Node} node
* @return {Element} element
*/
renderNode(node) {
switch (node.type) {
case 'image': {
return (props) => {
const { node, state } = props
const { data } = node
const isActive = state.selection.isFocused && state.blocks.includes(node)
const src = data.get('src')
return <img src={src} data-active={isActive} />
}
}
case 'paragraph': {
return (props) => <p>{props.children}</p>
}
}
}
}
/**

View File

@@ -5,10 +5,25 @@ import ReactDOM from 'react-dom'
import state from './state.json'
import { Map } from 'immutable'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
paragraph: props => <p>{props.children}</p>,
link: (props) => {
const { data } = props.node
const href = data.get('href')
return <a href={href}>{props.children}</a>
}
}
/**
* The links example.
*
* @type {Component} Links
* @type {Component}
*/
class Links extends React.Component {
@@ -114,7 +129,7 @@ class Links extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderNode={node => NODES[node.type]}
onChange={(state) => {
console.groupCollapsed('Change!')
console.log('Document:', state.document.toJS())
@@ -128,28 +143,6 @@ class Links extends React.Component {
)
}
/**
* Render our custom `node`.
*
* @param {Node} node
* @return {Element} element
*/
renderNode(node) {
switch (node.type) {
case 'link': {
return (props) => {
const { data } = props.node
const href = data.get('href')
return <a href={href}>{props.children}</a>
}
}
case 'paragraph': {
return (props) => <p>{props.children}</p>
}
}
}
}
/**

View File

@@ -3,13 +3,63 @@ import { Editor, Html, Raw } from '../..'
import React from 'react'
import state from './state.json'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
'bulleted-list': props => <ul>{props.children}</ul>,
'code': props => <pre><code>{props.children}</code></pre>,
'heading-one': props => <h1>{props.children}</h1>,
'heading-two': props => <h2>{props.children}</h2>,
'heading-three': props => <h3>{props.children}</h3>,
'heading-four': props => <h4>{props.children}</h4>,
'heading-five': props => <h5>{props.children}</h5>,
'heading-six': props => <h6>{props.children}</h6>,
'list-item': props => <li>{props.children}</li>,
'numbered-list': props => <ol>{props.children}</ol>,
'paragraph': props => <p>{props.children}</p>,
'quote': props => <blockquote>{props.children}</blockquote>,
'link': (props) => {
const { data } = props.node
const href = data.get('href')
return <a href={href}>{props.children}</a>
}
}
/**
* Mark renderers.
*
* @type {Object}
*/
const MARKS = {
bold: {
fontWeight: 'bold'
},
code: {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
},
italic: {
fontStyle: 'italic'
},
underlined: {
textDecoration: 'underline'
}
}
/**
* Tags to blocks.
*
* @type {Object}
*/
const BLOCKS = {
const BLOCK_TAGS = {
p: 'paragraph',
li: 'list-item',
ul: 'bulleted-list',
@@ -30,7 +80,7 @@ const BLOCKS = {
* @type {Object}
*/
const MARKS = {
const MARK_TAGS = {
strong: 'bold',
em: 'italic',
u: 'underline',
@@ -47,7 +97,7 @@ const MARKS = {
const RULES = [
{
deserialize(el, next) {
const block = BLOCKS[el.tagName]
const block = BLOCK_TAGS[el.tagName]
if (!block) return
return {
kind: 'block',
@@ -58,7 +108,7 @@ const RULES = [
},
{
deserialize(el, next) {
const mark = MARKS[el.tagName]
const mark = MARK_TAGS[el.tagName]
if (!mark) return
return {
kind: 'mark',
@@ -101,6 +151,8 @@ const RULES = [
/**
* Create a new HTML serializer with `RULES`.
*
* @type {Html}
*/
const serializer = new Html(RULES)
@@ -108,7 +160,7 @@ const serializer = new Html(RULES)
/**
* The rich text example.
*
* @type {Component} PasteHtml
* @type {Component}
*/
class PasteHtml extends React.Component {
@@ -133,8 +185,8 @@ class PasteHtml extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => NODES[node.type]}
renderMark={mark => MARKS[mark.type]}
onPaste={(...args) => this.onPaste(...args)}
onChange={(state) => {
console.groupCollapsed('Change!')
@@ -149,56 +201,6 @@ class PasteHtml extends React.Component {
)
}
renderNode(node) {
switch (node.type) {
case 'bulleted-list': return (props) => <ul>{props.children}</ul>
case 'code': return (props) => <pre><code>{props.children}</code></pre>
case 'heading-one': return (props) => <h1>{props.children}</h1>
case 'heading-two': return (props) => <h2>{props.children}</h2>
case 'heading-three': return (props) => <h3>{props.children}</h3>
case 'heading-four': return (props) => <h4>{props.children}</h4>
case 'heading-five': return (props) => <h5>{props.children}</h5>
case 'heading-six': return (props) => <h6>{props.children}</h6>
case 'list-item': return (props) => <li>{props.children}</li>
case 'numbered-list': return (props) => <ol>{props.children}</ol>
case 'paragraph': return (props) => <p>{props.children}</p>
case 'quote': return (props) => <blockquote>{props.children}</blockquote>
case 'link': return (props) => {
const { data } = props.node
const href = data.get('href')
return <a href={href}>{props.children}</a>
}
}
}
renderMark(mark) {
switch (mark.type) {
case 'bold': {
return {
fontWeight: 'bold'
}
}
case 'code': {
return {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
}
}
case 'italic': {
return {
fontStyle: 'italic'
}
}
case 'underlined': {
return {
textDecoration: 'underline'
}
}
}
}
}
/**

View File

@@ -34,15 +34,15 @@ function deserialize(string) {
*/
function serialize(state) {
return state.document.nodes
.map(node => node.text)
return state.blocks
.map(block => block.text)
.join('\n')
}
/**
* The plain text example.
*
* @type {Component} PlainText
* @type {Component}
*/
class PlainText extends React.Component {

View File

@@ -3,10 +3,50 @@ import { Editor, Mark, Raw } from '../..'
import React from 'react'
import state from './state.json'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
'block-quote': props => <blockquote>{props.children}</blockquote>,
'bulleted-list': props => <ul>{props.chidlren}</ul>,
'heading-one': props => <h1>{props.children}</h1>,
'heading-two': props => <h2>{props.children}</h2>,
'list-item': props => <li>{props.chidlren}</li>,
'numbered-list': props => <ol>{props.children}</ol>,
'paragraph': props => <p>{props.children}</p>
}
/**
* Mark renderers.
*
* @type {Object}
*/
const MARKS = {
bold: {
fontWeight: 'bold'
},
code: {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
},
italic: {
fontStyle: 'italic'
},
underlined: {
textDecoration: 'underline'
}
}
/**
* The rich text example.
*
* @type {Component} RichText
* @type {Component}
*/
class RichText extends React.Component {
@@ -101,8 +141,8 @@ class RichText extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => NODES[node.type]}
renderMark={mark => MARKS[mark.type]}
onChange={(state) => {
console.groupCollapsed('Change!')
console.log('Document:', state.document.toJS())
@@ -115,61 +155,6 @@ class RichText extends React.Component {
</div>
)
}
renderNode(node) {
switch (node.type) {
case 'block-quote': {
return (props) => <blockquote>{props.children}</blockquote>
}
case 'bulleted-list': {
return (props) => <ul>{props.chidlren}</ul>
}
case 'heading-one': {
return (props) => <h1>{props.children}</h1>
}
case 'heading-two': {
return (props) => <h2>{props.children}</h2>
}
case 'list-item': {
return (props) => <li>{props.chidlren}</li>
}
case 'numbered-list': {
return (props) => <ol>{props.children}</ol>
}
case 'paragraph': {
return (props) => <p>{props.children}</p>
}
}
}
renderMark(mark) {
switch (mark.type) {
case 'bold': {
return {
fontWeight: 'bold'
}
}
case 'code': {
return {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
}
}
case 'italic': {
return {
fontStyle: 'italic'
}
}
case 'underlined': {
return {
textDecoration: 'underline'
}
}
}
}
}
/**

View File

@@ -4,10 +4,35 @@ import React from 'react'
import keycode from 'keycode'
import state from './state.json'
/**
* Node renderers.
*
* @type {Object}
*/
const NODES = {
'paragraph': props => <p>{props.children}</p>,
'table': props => <table><tbody>{props.children}</tbody></table>,
'table-row': props => <tr>{props.children}</tr>,
'table-cell': props => <td>{props.children}</td>
}
/**
* Mark renderers.
*
* @type {Object}
*/
const MARKS = {
bold: {
fontWeight: 'bold'
}
}
/**
* The tables example.
*
* @type {Component} Tables
* @type {Component}
*/
class Tables extends React.Component {
@@ -33,8 +58,8 @@ class Tables extends React.Component {
<div className="editor">
<Editor
state={this.state.state}
renderNode={node => this.renderNode(node)}
renderMark={mark => this.renderMark(mark)}
renderNode={node => NODES[node.type]}
renderMark={mark => MARKS[mark.type]}
onKeyDown={(e, state) => this.onKeyDown(e, state)}
onChange={(state) => {
console.groupCollapsed('Change!')
@@ -49,47 +74,6 @@ class Tables extends React.Component {
)
}
/**
* Render each of our custom `mark` types.
*
* @param {Mark} mark
* @return {Component} component
*/
renderMark(mark) {
switch (mark.type) {
case 'bold': {
return {
fontWeight: 'bold'
}
}
}
}
/**
* Render each of our custom `node` types.
*
* @param {Node} node
* @return {Component} component
*/
renderNode(node) {
switch (node.type) {
case 'paragraph': {
return (props) => <p>{props.children}</p>
}
case 'table': {
return (props) => <table border="2px"><tbody>{props.children}</tbody></table>
}
case 'table-row': {
return (props) => <tr>{props.children}</tr>
}
case 'table-cell': {
return (props) => <td>{props.children}</td>
}
}
}
/**
* On key down, check for our specific key shortcuts.
*

View File

@@ -64,25 +64,21 @@ class Content extends React.Component {
*/
componentWillMount() {
console.log('is rendering')
this.tmp.isRendering = true
}
componentWillUpdate(props, state) {
console.log('is rendering')
this.tmp.isRendering = true
}
componentDidMount() {
setTimeout(() => {
console.log('not rendering')
this.tmp.isRendering = false
})
}
componentDidUpdate(props, state) {
setTimeout(() => {
console.log('not rendering')
this.tmp.isRendering = false
})
}
@@ -331,7 +327,6 @@ class Content extends React.Component {
*/
render() {
console.log('render contents')
const { state } = this.props
const { document } = state
const children = document.nodes

View File

@@ -44,7 +44,6 @@ class Text extends React.Component {
*/
render() {
console.log('render text:', this.props.node.key)
return (
<span>
{this.renderLeaves()}

View File

@@ -29,7 +29,7 @@ class Void extends React.Component {
return (
<Tag style={style}>
{this.renderSpacer()}
<div contenteditable={false}>{children}</div>
<div contentEditable={false}>{children}</div>
</Tag>
)
}