Implement image uploading for the raw editor
This commit is contained in:
parent
0a3676204e
commit
47512001ec
@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
|
|||||||
import { Editor, Plain, Mark } from 'slate';
|
import { Editor, Plain, Mark } from 'slate';
|
||||||
import Prism from 'prismjs';
|
import Prism from 'prismjs';
|
||||||
import PluginDropImages from 'slate-drop-or-paste-images';
|
import PluginDropImages from 'slate-drop-or-paste-images';
|
||||||
|
import MediaProxy from '../../../../valueObjects/MediaProxy';
|
||||||
import marks from './prismMarkdown';
|
import marks from './prismMarkdown';
|
||||||
import styles from './index.css';
|
import styles from './index.css';
|
||||||
|
|
||||||
@ -71,16 +72,6 @@ const SCHEMA = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const plugins = [
|
|
||||||
PluginDropImages({
|
|
||||||
applyTransform: (transform, file) => {
|
|
||||||
const state = Plain.deserialize(`\n\n\n\n`);
|
|
||||||
return transform
|
|
||||||
.insertFragment(state.get('document'));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
class RawEditor extends React.Component {
|
class RawEditor extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -92,9 +83,18 @@ class RawEditor extends React.Component {
|
|||||||
state: content
|
state: content
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.plugins = [
|
||||||
this.handleDocumentChange = this.handleDocumentChange.bind(this);
|
PluginDropImages({
|
||||||
|
applyTransform: (transform, file) => {
|
||||||
|
const mediaProxy = new MediaProxy(file.name, file);
|
||||||
|
console.log(mediaProxy);
|
||||||
|
const state = Plain.deserialize(`\n\n\n\n`);
|
||||||
|
props.onAddMedia(mediaProxy);
|
||||||
|
return transform
|
||||||
|
.insertFragment(state.get('document'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,11 +103,11 @@ class RawEditor extends React.Component {
|
|||||||
* It also have an onDocumentChange, that get's dispatched only when the actual
|
* It also have an onDocumentChange, that get's dispatched only when the actual
|
||||||
* content changes
|
* content changes
|
||||||
*/
|
*/
|
||||||
handleChange(state) {
|
handleChange = state => {
|
||||||
this.setState({ state });
|
this.setState({ state });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDocumentChange(document, state) {
|
handleDocumentChange = (document, state) => {
|
||||||
const content = Plain.serialize(state, { terse: true });
|
const content = Plain.serialize(state, { terse: true });
|
||||||
this.props.onChange(content);
|
this.props.onChange(content);
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ class RawEditor extends React.Component {
|
|||||||
schema={SCHEMA}
|
schema={SCHEMA}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
onDocumentChange={this.handleDocumentChange}
|
onDocumentChange={this.handleDocumentChange}
|
||||||
plugins={plugins}
|
plugins={this.plugins}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -130,6 +130,8 @@ class RawEditor extends React.Component {
|
|||||||
export default RawEditor;
|
export default RawEditor;
|
||||||
|
|
||||||
RawEditor.propTypes = {
|
RawEditor.propTypes = {
|
||||||
|
onAddMedia: PropTypes.func.isRequired,
|
||||||
|
getMedia: PropTypes.func.isRequired,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
value: PropTypes.node,
|
value: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,6 @@ import { DEFAULT_NODE, SCHEMA } from './schema';
|
|||||||
import { getNodes, getSyntaxes, getPlugins } from '../../richText';
|
import { getNodes, getSyntaxes, getPlugins } from '../../richText';
|
||||||
import StylesMenu from './StylesMenu';
|
import StylesMenu from './StylesMenu';
|
||||||
import BlockTypesMenu from './BlockTypesMenu';
|
import BlockTypesMenu from './BlockTypesMenu';
|
||||||
import styles from './index.css';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slate Render Configuration
|
* Slate Render Configuration
|
||||||
@ -178,11 +177,11 @@ class VisualEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When clicking a link, if the selection has a link in it, remove the link.
|
* When clicking a link, if the selection has a link in it, remove the link.
|
||||||
* Otherwise, add a new link with an href and text.
|
* Otherwise, add a new link with an href and text.
|
||||||
*
|
*
|
||||||
* @param {Event} e
|
* @param {Event} e
|
||||||
*/
|
*/
|
||||||
|
|
||||||
handleInlineClick(type, isActive) {
|
handleInlineClick(type, isActive) {
|
||||||
let { state } = this.state;
|
let { state } = this.state;
|
||||||
@ -212,17 +211,16 @@ class VisualEditor extends React.Component {
|
|||||||
this.setState({ state });
|
this.setState({ state });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
handleBlockTypeClick(type) {
|
handleBlockTypeClick(type) {
|
||||||
let { state } = this.state;
|
let { state } = this.state;
|
||||||
|
|
||||||
state = state
|
state = state
|
||||||
.transform()
|
.transform()
|
||||||
.insertBlock({
|
.insertBlock({
|
||||||
type: type,
|
type: type,
|
||||||
isVoid: true
|
isVoid: true
|
||||||
})
|
})
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
this.setState({ state }, this.focusAndAddParagraph);
|
this.setState({ state }, this.focusAndAddParagraph);
|
||||||
}
|
}
|
||||||
@ -277,18 +275,17 @@ class VisualEditor extends React.Component {
|
|||||||
.apply({
|
.apply({
|
||||||
snapshot: false
|
snapshot: false
|
||||||
});
|
});
|
||||||
this.setState({ state:normalized });
|
this.setState({ state: normalized });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
handleKeyDown(evt) {
|
handleKeyDown(evt) {
|
||||||
if (evt.shiftKey && evt.key === 'Enter') {
|
if (evt.shiftKey && evt.key === 'Enter') {
|
||||||
this.blockEdit = true;
|
this.blockEdit = true;
|
||||||
let { state } = this.state;
|
let { state } = this.state;
|
||||||
state = state
|
state = state
|
||||||
.transform()
|
.transform()
|
||||||
.insertText(' \n')
|
.insertText(' \n')
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
this.setState({ state });
|
this.setState({ state });
|
||||||
}
|
}
|
||||||
@ -300,12 +297,12 @@ class VisualEditor extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BlockTypesMenu
|
<BlockTypesMenu
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
plugins={getPlugins()}
|
plugins={getPlugins()}
|
||||||
position={this.menuPositions.blockTypesMenu}
|
position={this.menuPositions.blockTypesMenu}
|
||||||
onClickBlock={this.handleBlockTypeClick}
|
onClickBlock={this.handleBlockTypeClick}
|
||||||
onClickPlugin={this.handlePluginClick}
|
onClickPlugin={this.handlePluginClick}
|
||||||
onClickImage={this.handleImageClick}
|
onClickImage={this.handleImageClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -316,14 +313,14 @@ class VisualEditor extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StylesMenu
|
<StylesMenu
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
position={this.menuPositions.stylesMenu}
|
position={this.menuPositions.stylesMenu}
|
||||||
marks={this.state.state.marks}
|
marks={this.state.state.marks}
|
||||||
blocks={this.state.state.blocks}
|
blocks={this.state.state.blocks}
|
||||||
inlines={this.state.state.inlines}
|
inlines={this.state.state.inlines}
|
||||||
onClickMark={this.handleMarkStyleClick}
|
onClickMark={this.handleMarkStyleClick}
|
||||||
onClickInline={this.handleInlineClick}
|
onClickInline={this.handleInlineClick}
|
||||||
onClickBlock={this.handleBlockStyleClick}
|
onClickBlock={this.handleBlockStyleClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -334,12 +331,12 @@ class VisualEditor extends React.Component {
|
|||||||
{this.renderStylesMenu()}
|
{this.renderStylesMenu()}
|
||||||
{this.renderBlockTypesMenu()}
|
{this.renderBlockTypesMenu()}
|
||||||
<Editor
|
<Editor
|
||||||
placeholder={'Enter some rich text...'}
|
placeholder={'Enter some rich text...'}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
schema={SCHEMA}
|
schema={SCHEMA}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
onDocumentChange={this.handleDocumentChange}
|
onDocumentChange={this.handleDocumentChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -352,5 +349,5 @@ VisualEditor.propTypes = {
|
|||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
onAddMedia: PropTypes.func.isRequired,
|
onAddMedia: PropTypes.func.isRequired,
|
||||||
getMedia: PropTypes.func.isRequired,
|
getMedia: PropTypes.func.isRequired,
|
||||||
value: PropTypes.node,
|
value: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
@ -2,31 +2,32 @@ import React, { PropTypes } from 'react';
|
|||||||
import { getSyntaxes } from './richText';
|
import { getSyntaxes } from './richText';
|
||||||
import MarkupItReactRenderer from '../MarkupItReactRenderer/index';
|
import MarkupItReactRenderer from '../MarkupItReactRenderer/index';
|
||||||
|
|
||||||
const schema = {
|
const MarkdownPreview = ({ value, getMedia }) => {
|
||||||
'mediaproxy': ({ token }) => (
|
|
||||||
<img
|
|
||||||
src={token.getIn(['data', 'src'])}
|
|
||||||
alt={token.getIn(['data', 'alt'])}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
const MarkdownPreview = ({ value }) => {
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
'mediaproxy': ({ token }) => ( // eslint-disable-line
|
||||||
|
<img
|
||||||
|
src={getMedia(token.getIn(['data', 'src']))}
|
||||||
|
alt={token.getIn(['data', 'alt'])}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
const { markdown } = getSyntaxes();
|
const { markdown } = getSyntaxes();
|
||||||
return (
|
return (
|
||||||
<MarkupItReactRenderer
|
<MarkupItReactRenderer
|
||||||
value={value}
|
value={value}
|
||||||
syntax={markdown}
|
syntax={markdown}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
MarkdownPreview.propTypes = {
|
MarkdownPreview.propTypes = {
|
||||||
|
getMedia: PropTypes.func.isRequired,
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user