updated slate version
This commit is contained in:
parent
474abd8f78
commit
dea734ec21
@ -29,6 +29,7 @@ class MarkdownControl extends React.Component {
|
||||
onChange={onChange}
|
||||
onAddMedia={onAddMedia}
|
||||
getMedia={getMedia}
|
||||
registeredComponents={editor.get('registeredComponents')}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
|
@ -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,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['italic'].inside['bold'] = Prism.util.clone(Prism.languages.markdown['bold']);
|
||||
|
||||
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);
|
||||
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) {
|
||||
function renderDecorations(text, block) {
|
||||
let characters = text.characters.asMutable();
|
||||
const string = text.text;
|
||||
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() {
|
||||
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}
|
||||
|
@ -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}
|
||||
|
@ -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'
|
||||
}
|
||||
};
|
@ -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'
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user