updated slate version

This commit is contained in:
Cássio Zen 2016-08-17 09:52:06 -03:00
parent 474abd8f78
commit dea734ec21
5 changed files with 133 additions and 137 deletions

View File

@ -29,6 +29,7 @@ class MarkdownControl extends React.Component {
onChange={onChange} onChange={onChange}
onAddMedia={onAddMedia} onAddMedia={onAddMedia}
getMedia={getMedia} getMedia={getMedia}
registeredComponents={editor.get('registeredComponents')}
value={value} value={value}
/> />
</div> </div>

View File

@ -4,25 +4,6 @@ import Prism from 'prismjs';
import marks from './prismMarkdown'; import marks from './prismMarkdown';
import styles from './index.css'; 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.markdown = Prism.languages.extend('markup', {});
Prism.languages.insertBefore('markdown', 'prolog', marks); Prism.languages.insertBefore('markdown', 'prolog', marks);
@ -31,44 +12,7 @@ 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['bold'].inside['italic'] = Prism.util.clone(Prism.languages.markdown['italic']);
Prism.languages.markdown['italic'].inside['bold'] = Prism.util.clone(Prism.languages.markdown['bold']); Prism.languages.markdown['italic'].inside['bold'] = Prism.util.clone(Prism.languages.markdown['bold']);
class RawEditor extends React.Component { function renderDecorations(text, block) {
constructor(props) {
super(props);
const content = props.value ? Plain.deserialize(props.value) : Plain.deserialize('');
this.state = {
state: content
};
this.handleChange = this.handleChange.bind(this);
this.handleDocumentChange = this.handleDocumentChange.bind(this);
this.renderMark = this.renderMark.bind(this);
this.renderDecorations = this.renderDecorations.bind(this);
}
/**
* Slate keeps track of selections, scroll position etc.
* So, onChange gets dispatched on every interaction (click, arrows, everything...)
* It also have an onDocumentChange, that get's dispached only when the actual
* content changes
*/
handleChange(state) {
this.setState({ state });
}
handleDocumentChange(document, state) {
const content = Plain.serialize(state, { terse: true });
this.props.onChange(content);
}
renderMark(mark) {
return MARKS[mark.type] || {};
}
renderDecorations(text, block) {
let characters = text.characters.asMutable(); let characters = text.characters.asMutable();
const string = text.text; const string = text.text;
const grammar = Prism.languages.markdown; const grammar = Prism.languages.markdown;
@ -100,12 +44,71 @@ class RawEditor extends React.Component {
} }
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) {
super(props);
const content = props.value ? Plain.deserialize(props.value) : Plain.deserialize('');
this.state = {
state: content
};
this.handleChange = this.handleChange.bind(this);
this.handleDocumentChange = this.handleDocumentChange.bind(this);
}
/**
* Slate keeps track of selections, scroll position etc.
* So, onChange gets dispatched on every interaction (click, arrows, everything...)
* It also have an onDocumentChange, that get's dispached only when the actual
* content changes
*/
handleChange(state) {
this.setState({ state });
}
handleDocumentChange(document, state) {
const content = Plain.serialize(state, { terse: true });
this.props.onChange(content);
}
render() { render() {
return ( return (
<Editor <Editor
placeholder={'Enter some rich text...'} placeholder={'Enter some rich text...'}
state={this.state.state} state={this.state.state}
renderMark={this.renderMark} schema={SCHEMA}
onChange={this.handleChange} onChange={this.handleChange}
onDocumentChange={this.handleDocumentChange} onDocumentChange={this.handleDocumentChange}
renderDecorations={this.renderDecorations} renderDecorations={this.renderDecorations}

View File

@ -5,7 +5,7 @@ import position from 'selection-position';
import MarkupIt, { SlateUtils } from 'markup-it'; import MarkupIt, { SlateUtils } from 'markup-it';
import getSyntax from '../syntax'; import getSyntax from '../syntax';
import { emptyParagraphBlock } from '../constants'; import { emptyParagraphBlock } from '../constants';
import { DEFAULT_NODE, NODES, MARKS } from './localRenderers'; import { DEFAULT_NODE, SCHEMA } from './schema';
import StylesMenu from './StylesMenu'; import StylesMenu from './StylesMenu';
import BlockTypesMenu from './BlockTypesMenu'; import BlockTypesMenu from './BlockTypesMenu';
import styles from './index.css'; import styles from './index.css';
@ -22,7 +22,7 @@ class VisualEditor extends React.Component {
this.markdown = new MarkupIt(MarkdownSyntax); this.markdown = new MarkupIt(MarkdownSyntax);
this.customImageNodeRenderer = this.customImageNodeRenderer.bind(this); this.customImageNodeRenderer = this.customImageNodeRenderer.bind(this);
NODES['mediaproxy'] = this.customImageNodeRenderer; SCHEMA.nodes['mediaproxy'] = this.customImageNodeRenderer;
this.blockEdit = false; this.blockEdit = false;
this.menuPositions = { this.menuPositions = {
@ -63,8 +63,6 @@ class VisualEditor extends React.Component {
this.calculateHoverMenuPosition = _.throttle(this.calculateHoverMenuPosition.bind(this), 30); this.calculateHoverMenuPosition = _.throttle(this.calculateHoverMenuPosition.bind(this), 30);
this.calculateBlockMenuPosition = _.throttle(this.calculateBlockMenuPosition.bind(this), 100); this.calculateBlockMenuPosition = _.throttle(this.calculateBlockMenuPosition.bind(this), 100);
this.renderBlockTypesMenu = this.renderBlockTypesMenu.bind(this); this.renderBlockTypesMenu = this.renderBlockTypesMenu.bind(this);
this.renderNode = this.renderNode.bind(this);
this.renderMark = this.renderMark.bind(this);
} }
getMedia(src) { 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() { renderBlockTypesMenu() {
const currentBlock = this.state.state.blocks.get(0); const currentBlock = this.state.state.blocks.get(0);
const isOpen = (this.props.value !== undefined && currentBlock.isEmpty && currentBlock.type !== 'horizontal-rule'); const isOpen = (this.props.value !== undefined && currentBlock.isEmpty && currentBlock.type !== 'horizontal-rule');
@ -340,8 +328,7 @@ class VisualEditor extends React.Component {
<Editor <Editor
placeholder={'Enter some rich text...'} placeholder={'Enter some rich text...'}
state={this.state.state} state={this.state.state}
renderNode={this.renderNode} schema={SCHEMA}
renderMark={this.renderMark}
onChange={this.handleChange} onChange={this.handleChange}
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
onDocumentChange={this.handleDocumentChange} onDocumentChange={this.handleDocumentChange}

View File

@ -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'
}
};

View File

@ -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'
}
}
}