application/components/common/rich-editor2/plugins/embed.js
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import ToolbarButton from '../common/toolbar-button';
import {getEventTransfer} from 'slate-react';
import he from 'he';
import {ensureEmptyGraf} from '../util/ensure-empty-graf';
function defaultClickHandler() {
const {editor} = this;
const {editorContent} = this.state;
const hasEmbed = this.hasBlock('embed');
if (hasEmbed) {
editor.setBlocks('paragraph');
} else {
editor.setBlocks('embed');
}
}
export const SERIALIZER_RULES = [
{
serialize(obj, children) {
const danger = (children) => {
// renderToStaticMarkup converts all linebreaks to <br />, which is
// no bueno in these code blocks. Luckily the actual "static markup" is
// encoded so we can safely remove any <br /> elements.
const markup = ReactDOMServer.renderToStaticMarkup(children).replace(/\<br ?\/\>/ig, '');
return {
__html: he.decode(markup, {strict: false})
}
}
if (obj.object == 'block' && obj.type == 'embed') {
return <div className="embed" dangerouslySetInnerHTML={danger(children)}></div>;
}
}
}
];
export class EmbedButton extends ToolbarButton
{
handleOnClick(e) {
defaultClickHandler.call(this.props.editor, e);
}
getLabel() {
return <i className='fa fa-code'></i>;
}
}
export class EmbedNode extends React.Component
{
constructor(props) {
super(props);
this.parentEditor = this.props.editor;
}
render() {
return (
<pre {...this.props.attributes} className='embed-node'>
<code>
{this.props.children}
</code>
</pre>
)
}
}
let inEmbed = false;
export function embedHasCursor() {
return inEmbed;
}
export function EmbedPlugin(options) {
return {
renderEditor(props, editor, next) {
const children = next();
if (editor.value.blocks.some(inline => inline.type == 'embed')) {
inEmbed = true;
} else {
inEmbed = false;
}
return (
<React.Fragment>
{children}
</React.Fragment>
);
},
onPaste(e, editor, next) {
if (inEmbed == false) {
return next();
}
const xfer = getEventTransfer(e);
const text = xfer.text.replace(/\\n/ig, '');
const {start} = editor.value.selection;
const {document} = editor.value;
const sibling = editor.value.document.getNextNode(start.key);
if (document.getClosestBlock(start.key).get('type') == 'embed') {
editor.insertText(text);
} else {
editor.insertBlock({
object: 'block',
type: 'embed',
nodes: [
{
object: 'text',
leaves: [
{
text: text
}
]
}
]
});
}
if (!sibling) {
// make sure we have a blank line
ensureEmptyGraf(editor);
}
},
renderNode(props, editor, next) {
const {attributes, children} = props;
switch(props.node.type) {
case 'embed':
return <EmbedNode {...props} editor={editor}/>;
default:
return next();
}
}
};
};