Skip to content

Instantly share code, notes, and snippets.

@gscottolson
Created July 12, 2016 22:27
Show Gist options
  • Save gscottolson/855a690c5ebcb977cfb2735b625f0146 to your computer and use it in GitHub Desktop.
Save gscottolson/855a690c5ebcb977cfb2735b625f0146 to your computer and use it in GitHub Desktop.
import * as Ensure from '../../../../utils/lib/Ensure'
import markdownBlockDelimiter from './markdownBlockDelimiter'
import {BlockTypes, BlockTypeRegExps} from './Types'
import {
CharacterMetadata,
ContentState,
ContentBlock,
EditorState,
genKey,
} from 'draft-js'
import {List, OrderedSet} from 'immutable'
import {parse} from 'markdown-to-ast'
const unescapedAngleBracket = /^>/
const unescapedSquareBrackets = /([^\\])(\[|\])/g
function parseBlock(block, text = [], metadatas = [], style = '') {
const tree = (typeof block === 'string') ? parse(block) : block
if (tree.value) {
[...tree.value].forEach((char) => {
let config = null
switch (style) {
case 'Strong': config = {style: OrderedSet(['BOLD'])}; break
case 'Emphasis': config = {style: OrderedSet(['ITALIC'])}; break
case 'delete': config = {style: OrderedSet(['STRIKETHROUGH'])}; break
default: config = {}
}
text.push(char)
metadatas.push(CharacterMetadata.create(config))
})
}
if (tree.children) {
tree.children.forEach((child) => {
parseBlock(child, text, metadatas, tree.type)
})
}
return {metadatas, rawText: text.join('')}
}
function getBlockModel(text) {
Ensure.isString(text, 'text')
let blockText = text
let blockType = BlockTypes.Paragraph
let checked = false
if (BlockTypeRegExps.Title.test(text)) {
blockText = text.replace(BlockTypeRegExps.Title, '')
blockType = BlockTypes.Title
//
} else if (BlockTypeRegExps.Subtitle.test(text)) {
blockText = text.replace(BlockTypeRegExps.Subtitle, '')
blockType = BlockTypes.Subtitle
//
} else if (BlockTypeRegExps.Task.test(text)) {
blockText = text.replace(BlockTypeRegExps.Task, '')
blockType = BlockTypes.Task
checked = text.match(BlockTypeRegExps.Task)[1] !== ' '
//
} else if (BlockTypeRegExps.Bullet.test(text)) {
blockText = text.replace(BlockTypeRegExps.Bullet, '')
blockType = BlockTypes.Bullet
//
}
// We should be escaping [ and ] when serializing to Markdown.
// Find unescaped square brackets and escape before parsing Markdown.
if (unescapedSquareBrackets.test(blockText)) {
blockText = blockText.replace(unescapedSquareBrackets, '$1\\$2')
}
// Same story as above but with leading angle brackets
if (unescapedAngleBracket.test(blockText)) {
blockText = blockText.replace(unescapedAngleBracket, '\\>')
}
const {metadatas, rawText} = parseBlock(blockText)
return {blockText: rawText, blockType, checked, metadatas}
}
export default function convertFromMarkdownToEditorState(props, decorator) {
Ensure.isObject(props, 'props')
const markdown = props && props.content || ''
Ensure.isString(markdown, 'markdown')
const blocks = markdown.split(markdownBlockDelimiter)
const contentBlocks = []
const taskBlockMap = {}
for (const text of blocks) {
const {blockText, blockType, checked, metadatas} = getBlockModel(text)
const blockKey = genKey()
taskBlockMap[blockKey] = checked
contentBlocks.push(new ContentBlock({
characterList: new List(metadatas),
depth: 0,
key: blockKey,
text: blockText,
type: blockType,
}))
}
const contentState = ContentState.createFromBlockArray(contentBlocks)
const editorState = EditorState.createWithContent(contentState, decorator)
return {editorState, taskBlockMap}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment