Skip to content

Instantly share code, notes, and snippets.

@isabellachen
Created March 13, 2020 14:19
Show Gist options
  • Save isabellachen/623a6c9587f5437b1c189d09945e6bd8 to your computer and use it in GitHub Desktop.
Save isabellachen/623a6c9587f5437b1c189d09945e6bd8 to your computer and use it in GitHub Desktop.
sidra draftToMarkdown custom style handler
import { convertFromRaw, convertToRaw, Editor, EditorState, RichUtils } from 'draft-js';
import { draftToMarkdown, markdownToDraft } from 'markdown-draft-js';
import React, { useEffect, useState } from 'react';
import { useIsFirstRender } from '~/core/utils';
import './markdown-editor.scss';
import { BlockTypeControls } from './MarkdownEditorBlockTypeControls';
import { InlineStyleControls } from './MarkdownEditorInlineStyleControls';
type MarkdownEditorProps = {
markdown: string;
updateMarkdownEdit: React.Dispatch<React.SetStateAction<string>>;
};
export const MarkdownEditor = ({ markdown, updateMarkdownEdit }: MarkdownEditorProps) => {
let domEditor: Editor;
const [editorState, updateEditorState] = useState(EditorState.createEmpty());
const isFirstRender = useIsFirstRender();
useEffect(() => {
domEditor.focus();
if (markdown) {
const rawData = markdownToDraft(markdown);
const contentState = convertFromRaw(rawData);
const editorStateFromExistingMarkdown = EditorState.createWithContent(contentState);
updateEditorState(editorStateFromExistingMarkdown);
}
}, []);
const toggleInlineStyle = (inlineStyle: string) => {
const newEditorState = RichUtils.toggleInlineStyle(editorState, inlineStyle);
updateEditorState(newEditorState);
};
const toggleBlockType = (blockType: string) => {
const newEditorState = RichUtils.toggleBlockType(editorState, blockType);
updateEditorState(newEditorState);
};
const setDomEditorRef = (ref: Editor) => {
domEditor = ref;
};
const focusEditor = () => {
domEditor.focus();
};
const customStyleHandlersToMarkdown = {
styleItems: {
UNDERLINE: {
open: function() {
return '<u>';
},
close: function() {
return '</u>';
},
},
},
};
const onChangeInEditor = (e: EditorState) => {
if (isFirstRender) {
return;
}
updateEditorState(e);
const contentState = editorState.getCurrentContent();
const rawObject = convertToRaw(contentState);
const markdownString = draftToMarkdown(rawObject, customStyleHandlersToMarkdown);
updateMarkdownEdit(markdownString);
};
return (
<>
<BlockTypeControls editorState={editorState} onToggle={toggleBlockType} />
<InlineStyleControls editorState={editorState} onToggle={toggleInlineStyle} />
<div className="markdown-editor__container">
<div className="markdown-editor__inner" onClick={focusEditor}>
<Editor editorState={editorState} onChange={onChangeInEditor} ref={setDomEditorRef} />
</div>
</div>
</>
);
};
@isabellachen
Copy link
Author

import { EditorState } from 'draft-js';
import React from 'react';
import BoldIcon from '~/assets/icons/markdown-editor/bold.svg';
import ItalicIcon from '~/assets/icons/markdown-editor/italic.svg';
import UnderlineIcon from '~/assets/icons/markdown-editor/underline.svg';
import { StyleButton } from './MarkdownEditorStyleButton';

const INLINE_STYLES = [
  { label: 'Bold', style: 'BOLD', iconSrc: BoldIcon },
  { label: 'Italic', style: 'ITALIC', iconSrc: ItalicIcon },
  { label: 'Underline', style: 'UNDERLINE', iconSrc: UnderlineIcon },
];

type InlineStyleControlsProps = {
  editorState: EditorState;
  onToggle: (style: string) => void;
};

export const InlineStyleControls = ({ editorState, onToggle }: InlineStyleControlsProps) => {
  const currentStyle = editorState.getCurrentInlineStyle();

  return (
    <div className="markdown-editor__controls">
      {INLINE_STYLES.map(type => (
        <StyleButton
          key={type.label}
          active={currentStyle.has(type.style)}
          iconSrc={type.iconSrc}
          label={type.label}
          style={type.style}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment