From eeb97c0611d71192a4fb3a85e1426cdad6e0e67f Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Sat, 13 Aug 2016 16:48:21 -0700 Subject: [PATCH] add rendering of components from schema --- examples/auto-markdown/index.js | 42 ------------------------- examples/rich-text/index.js | 31 +++++++------------ lib/components/content.js | 7 +++-- lib/components/editor.js | 22 ++++---------- lib/components/node.js | 28 +++++------------ lib/models/schema.js | 54 ++++++++++++++++++--------------- 6 files changed, 57 insertions(+), 127 deletions(-) diff --git a/examples/auto-markdown/index.js b/examples/auto-markdown/index.js index acd0b8f26..ac141c868 100644 --- a/examples/auto-markdown/index.js +++ b/examples/auto-markdown/index.js @@ -9,48 +9,6 @@ import initialState from './state.json' * @type {Object} */ -const schema = { - rules: [ - { - match: { type: 'block-quote' }, - component: props =>
{props.children}
- }, - { - match: { type: 'bulleted-list' }, - component: props => , - }, - { - match: { type: 'heading-one' }, - component: props =>

{props.children}

, - }, - { - match: { type: 'heading-two' }, - component: props =>

{props.children}

, - }, - { - match: { type: 'heading-three' }, - component: props =>

{props.children}

, - }, - { - match: { type: 'heading-four' }, - component: props =>

{props.children}

, - }, - { - match: { type: 'heading-five' }, - component: props =>
{props.children}
, - }, - { - match: { type: 'heading-six' }, - component: props =>
{props.children}
, - }, - { - match: { type: 'list-item' }, - component: props =>
  • {props.children}
  • , - }, - ] -} - - const NODES = { 'block-quote': props =>
    {props.children}
    , 'bulleted-list': props => , diff --git a/examples/rich-text/index.js b/examples/rich-text/index.js index 55a1ec590..029620d33 100644 --- a/examples/rich-text/index.js +++ b/examples/rich-text/index.js @@ -10,18 +10,20 @@ import initialState from './state.json' const DEFAULT_NODE = 'paragraph' /** - * Define a set of node renderers. + * Define a schema. * * @type {Object} */ -const NODES = { - 'block-quote': (props) =>
    {props.children}
    , - 'bulleted-list': props => , - 'heading-one': props =>

    {props.children}

    , - 'heading-two': props =>

    {props.children}

    , - 'list-item': props =>
  • {props.children}
  • , - 'numbered-list': props =>
      {props.children}
    +const schema = { + nodes: { + 'block-quote': props =>
    {props.children}
    , + 'bulleted-list': props => , + 'heading-one': props =>

    {props.children}

    , + 'heading-two': props =>

    {props.children}

    , + 'list-item': props =>
  • {props.children}
  • , + 'numbered-list': props =>
      {props.children}
    , + } } /** @@ -302,8 +304,8 @@ class RichText extends React.Component {
    { - return NODES[node.type] - } - /** * Return a mark renderer for a Slate `mark`. * diff --git a/lib/components/content.js b/lib/components/content.js index 5ac7188f3..0b3532803 100644 --- a/lib/components/content.js +++ b/lib/components/content.js @@ -57,7 +57,7 @@ class Content extends React.Component { readOnly: React.PropTypes.bool.isRequired, renderDecorations: React.PropTypes.func.isRequired, renderMark: React.PropTypes.func.isRequired, - renderNode: React.PropTypes.func.isRequired, + schema: React.PropTypes.object, spellCheck: React.PropTypes.bool.isRequired, state: React.PropTypes.object.isRequired, style: React.PropTypes.object @@ -102,6 +102,7 @@ class Content extends React.Component { return ( props.className != this.props.className || props.readOnly != this.props.readOnly || + props.schema != this.props.schema || props.spellCheck != this.props.spellCheck || props.state != this.props.state || props.style != this.props.style @@ -683,17 +684,17 @@ class Content extends React.Component { */ renderNode = (node) => { - const { editor, renderDecorations, renderMark, renderNode, state } = this.props + const { editor, renderDecorations, renderMark, schema, state } = this.props return ( ) } diff --git a/lib/components/editor.js b/lib/components/editor.js index 9d6e5be13..5c6754c8e 100644 --- a/lib/components/editor.js +++ b/lib/components/editor.js @@ -65,6 +65,7 @@ class Editor extends React.Component { renderDecorations: React.PropTypes.func, renderMark: React.PropTypes.func, renderNode: React.PropTypes.func, + schema: React.PropTypes.object, spellCheck: React.PropTypes.bool, state: React.PropTypes.object.isRequired, style: React.PropTypes.object @@ -118,6 +119,11 @@ class Editor extends React.Component { this.setState({ plugins, schema }) } + else if (props.schema != this.props.schema) { + const schema = this.resolveSchema(this.state.plugins) + this.setState({ schema }) + } + this.setState({ state: this.onBeforeChange(props.state) }) @@ -262,7 +268,6 @@ class Editor extends React.Component { readOnly={this.props.readOnly} renderDecorations={this.renderDecorations} renderMark={this.renderMark} - renderNode={this.renderNode} schema={this.state.schema} spellCheck={this.props.spellCheck} state={this.state.state} @@ -317,21 +322,6 @@ class Editor extends React.Component { } } - /** - * Render a `node`, cascading through the plugins. - * - * @param {Node} node - * @return {Element} - */ - - renderNode = (node) => { - for (const plugin of this.state.plugins) { - if (!plugin.renderNode) continue - const component = plugin.renderNode(node, this.state.state, this) - if (component) return component - } - } - /** * Resolve the editor's current plugins from `props` when they change. * diff --git a/lib/components/node.js b/lib/components/node.js index 3d6c68c4d..19b83d40d 100644 --- a/lib/components/node.js +++ b/lib/components/node.js @@ -36,20 +36,10 @@ class Node extends React.Component { node: React.PropTypes.object.isRequired, renderDecorations: React.PropTypes.func.isRequired, renderMark: React.PropTypes.func.isRequired, - renderNode: React.PropTypes.func.isRequired, + schema: React.PropTypes.object.isRequired, state: React.PropTypes.object.isRequired }; - /** - * Default properties. - * - * @type {Object} - */ - - static defaultProps = { - style: {} - }; - /** * Constructor. * @@ -58,11 +48,9 @@ class Node extends React.Component { constructor(props) { super(props) + const { node, schema } = props this.state = {} - - if (props.node.kind != 'text') { - this.state.Component = props.renderNode(props.node) - } + this.state.Component = node.kind == 'text' ? null : node.getComponent(schema) } /** @@ -88,10 +76,8 @@ class Node extends React.Component { componentWillReceiveProps = (props) => { if (props.node.kind == 'text') return if (props.node == this.props.node) return - - this.setState({ - Component: props.renderNode(props.node) - }) + const Component = props.node.getComponent(props.schema) + this.setState({ Component }) } /** @@ -228,18 +214,18 @@ class Node extends React.Component { */ renderNode = (child) => { - const { editor, node, renderDecorations, renderMark, renderNode, state } = this.props + const { editor, node, renderDecorations, renderMark, schema, state } = this.props const block = node.kind == 'block' ? node : this.props.block return ( ) } diff --git a/lib/models/schema.js b/lib/models/schema.js index ab316ee64..bb28b8c93 100644 --- a/lib/models/schema.js +++ b/lib/models/schema.js @@ -1,7 +1,6 @@ import RULES from '../constants/rules' import includes from 'lodash/includes' -import isReactComponent from '../utils/is-react-component' import typeOf from 'type-of' import memoize from '../utils/memoize' import { Record } from 'immutable' @@ -201,20 +200,22 @@ function normalizeProperties(properties) { if (nodes) { for (const key in nodes) { const value = nodes[key] - let rule - - if (isReactComponent(value)) { - rule.match = { type: key } - rule.component = value - } else { - rule = { - kinds: ['block', 'inline'], - type: key, - ...value - } + const match = { + kinds: ['block', 'inline'], + type: key, } - rules.push(rule) + if (value.component) { + rules.push({ + match, + ...value, + }) + } else { + rules.push({ + match, + component: value + }) + } } } @@ -222,20 +223,22 @@ function normalizeProperties(properties) { if (marks) { for (const key in marks) { const value = marks[key] - let rule - - if (rule.match) { - rule = { - kind: 'mark', - type: key, - ...value - } - } else { - rule.match = { type: key } - rule.component = value + const match = { + kind: 'mark', + type: key, } - rules.push(rule) + if (value.component) { + rules.push({ + match, + ...value, + }) + } else { + rules.push({ + match, + component: value + }) + } } } @@ -253,6 +256,7 @@ function normalizeProperties(properties) { function normalizeRule(rule) { return { + ...rule, match: normalizeMatch(rule.match), validate: normalizeValidate(rule.validate), transform: normalizeTransform(rule.transform),