From dea734ec21994335d2f6ba76a2fb214735fe5691 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A1ssio=20Zen?= <cassiozen@gmail.com>
Date: Wed, 17 Aug 2016 09:52:06 -0300
Subject: [PATCH] updated slate version

---
 src/components/Widgets/MarkdownControl.js     |   7 +-
 .../RawEditor/index.js                        | 119 +++++++++---------
 .../VisualEditor/index.js                     |  19 +--
 .../VisualEditor/localRenderers.js            |  60 ---------
 .../VisualEditor/schema.js                    |  65 ++++++++++
 5 files changed, 133 insertions(+), 137 deletions(-)
 delete mode 100644 src/components/Widgets/MarkdownControlElements/VisualEditor/localRenderers.js
 create mode 100644 src/components/Widgets/MarkdownControlElements/VisualEditor/schema.js

diff --git a/src/components/Widgets/MarkdownControl.js b/src/components/Widgets/MarkdownControl.js
index 0e7e9850..a4c6f22a 100644
--- a/src/components/Widgets/MarkdownControl.js
+++ b/src/components/Widgets/MarkdownControl.js
@@ -5,17 +5,17 @@ import { connect } from 'react-redux';
 import { switchVisualMode } from '../../actions/editor';
 
 class MarkdownControl extends React.Component {
-  constructor(props){
+  constructor(props) {
     super(props);
     this.useVisualEditor = this.useVisualEditor.bind(this);
     this.useRawEditor = this.useRawEditor.bind(this);
   }
 
-  useVisualEditor(){
+  useVisualEditor() {
     this.props.switchVisualMode(true);
   }
 
-  useRawEditor(){
+  useRawEditor() {
     this.props.switchVisualMode(false);
   }
 
@@ -29,6 +29,7 @@ class MarkdownControl extends React.Component {
               onChange={onChange}
               onAddMedia={onAddMedia}
               getMedia={getMedia}
+              registeredComponents={editor.get('registeredComponents')}
               value={value}
           />
         </div>
diff --git a/src/components/Widgets/MarkdownControlElements/RawEditor/index.js b/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
index 2cabeaa0..175f2471 100644
--- a/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
+++ b/src/components/Widgets/MarkdownControlElements/RawEditor/index.js
@@ -4,25 +4,6 @@ import Prism from 'prismjs';
 import marks from './prismMarkdown';
 import styles from './index.css';
 
-const MARKS = {
-  'highlight-comment': {
-    opacity: '0.33'
-  },
-  'highlight-important': {
-    fontWeight: 'bold',
-    color: '#006',
-  },
-  'highlight-keyword': {
-    fontWeight: 'bold',
-    color: '#006',
-  },
-  'highlight-url': {
-    color: '#006',
-  },
-  'highlight-punctuation': {
-    color: '#006',
-  }
-};
 
 Prism.languages.markdown = Prism.languages.extend('markup', {});
 Prism.languages.insertBefore('markdown', 'prolog', marks);
@@ -31,6 +12,66 @@ Prism.languages.markdown['italic'].inside['url'] = Prism.util.clone(Prism.langua
 Prism.languages.markdown['bold'].inside['italic'] = Prism.util.clone(Prism.languages.markdown['italic']);
 Prism.languages.markdown['italic'].inside['bold'] = Prism.util.clone(Prism.languages.markdown['bold']);
 
+function renderDecorations(text, block) {
+  let characters = text.characters.asMutable();
+  const string = text.text;
+  const grammar = Prism.languages.markdown;
+  const tokens = Prism.tokenize(string, grammar);
+  let offset = 0;
+
+  for (const token of tokens) {
+    if (typeof token == 'string') {
+      offset += token.length;
+      continue;
+    }
+
+    const length = offset + token.matchedStr.length;
+    const name = token.alias || token.type;
+    const type = `highlight-${name}`;
+
+    for (let i = offset; i < length; i++) {
+      let char = characters.get(i);
+      let { marks } = char;
+      marks = marks.add(Mark.create({ type }));
+      char = char.merge({ marks });
+      characters = characters.set(i, char);
+    }
+
+    offset = length;
+  }
+
+  return characters.asImmutable();
+}
+
+
+const SCHEMA = {
+  rules: [
+    {
+      match: (object) => object.kind == 'block',
+      decorate: renderDecorations
+    }
+  ],
+  marks: {
+    'highlight-comment': {
+      opacity: '0.33'
+    },
+    'highlight-important': {
+      fontWeight: 'bold',
+      color: '#006',
+    },
+    'highlight-keyword': {
+      fontWeight: 'bold',
+      color: '#006',
+    },
+    'highlight-url': {
+      color: '#006',
+    },
+    'highlight-punctuation': {
+      color: '#006',
+    }
+  }
+};
+
 class RawEditor extends React.Component {
 
   constructor(props) {
@@ -44,8 +85,6 @@ class RawEditor extends React.Component {
 
     this.handleChange = this.handleChange.bind(this);
     this.handleDocumentChange = this.handleDocumentChange.bind(this);
-    this.renderMark = this.renderMark.bind(this);
-    this.renderDecorations = this.renderDecorations.bind(this);
 
   }
 
@@ -64,48 +103,12 @@ class RawEditor extends React.Component {
     this.props.onChange(content);
   }
 
-  renderMark(mark) {
-    return MARKS[mark.type] || {};
-  }
-
-  renderDecorations(text, block) {
-    let characters = text.characters.asMutable();
-    const string = text.text;
-    const grammar = Prism.languages.markdown;
-    const tokens = Prism.tokenize(string, grammar);
-    let offset = 0;
-
-    for (const token of tokens) {
-      if (typeof token == 'string') {
-        offset += token.length;
-        continue;
-      }
-
-      const length = offset + token.matchedStr.length;
-      const name = token.alias || token.type;
-      const type = `highlight-${name}`;
-
-      for (let i = offset; i < length; i++) {
-        let char = characters.get(i);
-        let { marks } = char;
-        marks = marks.add(Mark.create({ type }));
-        char = char.merge({ marks });
-        characters = characters.set(i, char);
-      }
-
-      offset = length;
-    }
-
-    return characters.asImmutable();
-  }
-
-
   render() {
     return (
       <Editor
           placeholder={'Enter some rich text...'}
           state={this.state.state}
-          renderMark={this.renderMark}
+          schema={SCHEMA}
           onChange={this.handleChange}
           onDocumentChange={this.handleDocumentChange}
           renderDecorations={this.renderDecorations}
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
index 33dea48d..86dcc739 100644
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/index.js
@@ -5,7 +5,7 @@ import position from 'selection-position';
 import MarkupIt, { SlateUtils } from 'markup-it';
 import getSyntax from '../syntax';
 import { emptyParagraphBlock } from '../constants';
-import { DEFAULT_NODE, NODES, MARKS } from './localRenderers';
+import { DEFAULT_NODE, SCHEMA } from './schema';
 import StylesMenu from './StylesMenu';
 import BlockTypesMenu from './BlockTypesMenu';
 import styles from './index.css';
@@ -22,7 +22,7 @@ class VisualEditor extends React.Component {
     this.markdown = new MarkupIt(MarkdownSyntax);
 
     this.customImageNodeRenderer = this.customImageNodeRenderer.bind(this);
-    NODES['mediaproxy'] = this.customImageNodeRenderer;
+    SCHEMA.nodes['mediaproxy'] = this.customImageNodeRenderer;
 
     this.blockEdit = false;
     this.menuPositions = {
@@ -63,8 +63,6 @@ class VisualEditor extends React.Component {
     this.calculateHoverMenuPosition = _.throttle(this.calculateHoverMenuPosition.bind(this), 30);
     this.calculateBlockMenuPosition = _.throttle(this.calculateBlockMenuPosition.bind(this), 100);
     this.renderBlockTypesMenu = this.renderBlockTypesMenu.bind(this);
-    this.renderNode = this.renderNode.bind(this);
-    this.renderMark = this.renderMark.bind(this);
   }
 
   getMedia(src) {
@@ -290,16 +288,6 @@ class VisualEditor extends React.Component {
     }
   }
 
-  /**
-   * Return renderers for Slate
-   */
-  renderNode(node) {
-    return NODES[node.type];
-  }
-  renderMark(mark) {
-    return MARKS[mark.type];
-  }
-
   renderBlockTypesMenu() {
     const currentBlock = this.state.state.blocks.get(0);
     const isOpen = (this.props.value !== undefined && currentBlock.isEmpty && currentBlock.type !== 'horizontal-rule');
@@ -340,8 +328,7 @@ class VisualEditor extends React.Component {
         <Editor
             placeholder={'Enter some rich text...'}
             state={this.state.state}
-            renderNode={this.renderNode}
-            renderMark={this.renderMark}
+            schema={SCHEMA}
             onChange={this.handleChange}
             onKeyDown={this.handleKeyDown}
             onDocumentChange={this.handleDocumentChange}
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/localRenderers.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/localRenderers.js
deleted file mode 100644
index 2dfac7d2..00000000
--- a/src/components/Widgets/MarkdownControlElements/VisualEditor/localRenderers.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import React from 'react';
-import Block from './Block';
-import styles from './index.css';
-
-/* eslint react/prop-types: 0, react/no-multi-comp: 0 */
-
-// Define the default node type.
-export const DEFAULT_NODE = 'paragraph';
-
-// Local node renderers.
-export const NODES = {
-  'blockquote': (props) => <Block type='blockquote' {...props.attributes}>{props.children}</Block>,
-  'unordered_list': props => <Block type='List'><ul {...props.attributes}>{props.children}</ul></Block>,
-  'header_one': props => <Block type='Heading1' {...props.attributes}>{props.children}</Block>,
-  'header_two': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
-  'header_three': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
-  'header_four': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
-  'header_five': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
-  'header_six': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
-  'list_item': props => <li {...props.attributes}>{props.children}</li>,
-  'paragraph': props => <Block type='Paragraph' {...props.attributes}>{props.children}</Block>,
-  'hr': props => {
-    const { node, state } = props;
-    const isFocused = state.selection.hasEdgeIn(node);
-    const className = isFocused ? styles.active : null;
-    return (
-      <hr className={className} {...props.attributes} />
-    );
-  },
-  'link': (props) => {
-    const { data } = props.node;
-    const href = data.get('href');
-    return <a {...props.attributes} href={href}>{props.children}</a>;
-  },
-  'image': (props) => {
-    const { node, state } = props;
-    const isFocused = state.selection.hasEdgeIn(node);
-    const className = isFocused ? styles.active : null;
-    const src = node.data.get('src');
-    return (
-      <img {...props.attributes} src={src} className={className} />
-    );
-  }
-};
-
-// Local mark renderers.
-export const MARKS = {
-  BOLD: {
-    fontWeight: 'bold'
-  },
-  ITALIC: {
-    fontStyle: 'italic'
-  },
-  CODE: {
-    fontFamily: 'monospace',
-    backgroundColor: '#eee',
-    padding: '3px',
-    borderRadius: '4px'
-  }
-};
diff --git a/src/components/Widgets/MarkdownControlElements/VisualEditor/schema.js b/src/components/Widgets/MarkdownControlElements/VisualEditor/schema.js
new file mode 100644
index 00000000..ea00ade2
--- /dev/null
+++ b/src/components/Widgets/MarkdownControlElements/VisualEditor/schema.js
@@ -0,0 +1,65 @@
+import React from 'react';
+import Block from './Block';
+import styles from './index.css';
+
+/* eslint react/prop-types: 0, react/no-multi-comp: 0 */
+
+// Define the default node type.
+export const DEFAULT_NODE = 'paragraph';
+
+/**
+ * Define a schema.
+ *
+ * @type {Object}
+ */
+
+export const SCHEMA = {
+  nodes: {
+    'blockquote': (props) => <Block type='blockquote' {...props.attributes}>{props.children}</Block>,
+    'unordered_list': props => <Block type='List'><ul {...props.attributes}>{props.children}</ul></Block>,
+    'header_one': props => <Block type='Heading1' {...props.attributes}>{props.children}</Block>,
+    'header_two': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
+    'header_three': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
+    'header_four': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
+    'header_five': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
+    'header_six': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
+    'list_item': props => <li {...props.attributes}>{props.children}</li>,
+    'paragraph': props => <Block type='Paragraph' {...props.attributes}>{props.children}</Block>,
+    'hr': props => {
+      const { node, state } = props;
+      const isFocused = state.selection.hasEdgeIn(node);
+      const className = isFocused ? styles.active : null;
+      return (
+        <hr className={className} {...props.attributes} />
+      );
+    },
+    'link': (props) => {
+      const { data } = props.node;
+      const href = data.get('href');
+      return <a {...props.attributes} href={href}>{props.children}</a>;
+    },
+    'image': (props) => {
+      const { node, state } = props;
+      const isFocused = state.selection.hasEdgeIn(node);
+      const className = isFocused ? styles.active : null;
+      const src = node.data.get('src');
+      return (
+        <img {...props.attributes} src={src} className={className} />
+      );
+    }
+  },
+  marks: {
+    BOLD: {
+      fontWeight: 'bold'
+    },
+    ITALIC: {
+      fontStyle: 'italic'
+    },
+    CODE: {
+      fontFamily: 'monospace',
+      backgroundColor: '#eee',
+      padding: '3px',
+      borderRadius: '4px'
+    }
+  }
+}