Home Reference Source

application/components/common/rich-editor2/plugins/embed.js

  1. import React from 'react';
  2. import ReactDOMServer from 'react-dom/server';
  3. import ToolbarButton from '../common/toolbar-button';
  4. import {getEventTransfer} from 'slate-react';
  5. import he from 'he';
  6. import {ensureEmptyGraf} from '../util/ensure-empty-graf';
  7.  
  8. function defaultClickHandler() {
  9. const {editor} = this;
  10. const {editorContent} = this.state;
  11. const hasEmbed = this.hasBlock('embed');
  12.  
  13. if (hasEmbed) {
  14. editor.setBlocks('paragraph');
  15. } else {
  16. editor.setBlocks('embed');
  17. }
  18.  
  19. }
  20.  
  21. export const SERIALIZER_RULES = [
  22.  
  23. {
  24. serialize(obj, children) {
  25. const danger = (children) => {
  26. // renderToStaticMarkup converts all linebreaks to <br />, which is
  27. // no bueno in these code blocks. Luckily the actual "static markup" is
  28. // encoded so we can safely remove any <br /> elements.
  29. const markup = ReactDOMServer.renderToStaticMarkup(children).replace(/\<br ?\/\>/ig, '');
  30.  
  31. return {
  32. __html: he.decode(markup, {strict: false})
  33. }
  34. }
  35. if (obj.object == 'block' && obj.type == 'embed') {
  36. return <div className="embed" dangerouslySetInnerHTML={danger(children)}></div>;
  37. }
  38. }
  39. }
  40. ];
  41.  
  42. export class EmbedButton extends ToolbarButton
  43. {
  44. handleOnClick(e) {
  45. defaultClickHandler.call(this.props.editor, e);
  46. }
  47.  
  48. getLabel() {
  49. return <i className='fa fa-code'></i>;
  50. }
  51. }
  52.  
  53. export class EmbedNode extends React.Component
  54. {
  55. constructor(props) {
  56. super(props);
  57.  
  58. this.parentEditor = this.props.editor;
  59. }
  60.  
  61. render() {
  62. return (
  63. <pre {...this.props.attributes} className='embed-node'>
  64. <code>
  65. {this.props.children}
  66. </code>
  67. </pre>
  68. )
  69. }
  70. }
  71. let inEmbed = false;
  72.  
  73. export function embedHasCursor() {
  74. return inEmbed;
  75. }
  76.  
  77. export function EmbedPlugin(options) {
  78.  
  79. return {
  80. renderEditor(props, editor, next) {
  81. const children = next();
  82. if (editor.value.blocks.some(inline => inline.type == 'embed')) {
  83. inEmbed = true;
  84. } else {
  85. inEmbed = false;
  86. }
  87. return (
  88. <React.Fragment>
  89. {children}
  90. </React.Fragment>
  91. );
  92. },
  93. onPaste(e, editor, next) {
  94.  
  95. if (inEmbed == false) {
  96. return next();
  97. }
  98. const xfer = getEventTransfer(e);
  99. const text = xfer.text.replace(/\\n/ig, '');
  100.  
  101. const {start} = editor.value.selection;
  102. const {document} = editor.value;
  103.  
  104. const sibling = editor.value.document.getNextNode(start.key);
  105.  
  106. if (document.getClosestBlock(start.key).get('type') == 'embed') {
  107. editor.insertText(text);
  108. } else {
  109. editor.insertBlock({
  110. object: 'block',
  111. type: 'embed',
  112. nodes: [
  113. {
  114. object: 'text',
  115. leaves: [
  116. {
  117. text: text
  118. }
  119. ]
  120. }
  121. ]
  122. });
  123. }
  124. if (!sibling) {
  125. // make sure we have a blank line
  126. ensureEmptyGraf(editor);
  127. }
  128.  
  129. },
  130. renderNode(props, editor, next) {
  131. const {attributes, children} = props;
  132.  
  133. switch(props.node.type) {
  134. case 'embed':
  135. return <EmbedNode {...props} editor={editor}/>;
  136. default:
  137. return next();
  138. }
  139.  
  140. }
  141. };
  142. };