Last active
January 7, 2018 06:13
-
-
Save zGrav/440fdbe83d7eca8455362ccfd2e58662 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Html from 'slate-html-serializer'; | |
// import React from 'react'; | |
// import { FunctionTypes } from 'constants/editor/ViewModel'; | |
// import { Nodes } from 'components/editor'; | |
import { getEventTransfer } from 'slate-react'; | |
import { BlockTypes } from 'constants/editor'; | |
import { Block } from 'slate'; | |
const MARK_TAGS = { | |
strong: 'bold', | |
em: 'italic', | |
u: 'underline', | |
s: 'strikethrough', | |
code: 'code', | |
}; | |
const BLOCK_TAGS = { | |
blockquote: { | |
type: BlockTypes.PARAGRAPH, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
pre: { | |
type: BlockTypes.PARAGRAPH, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
p: { | |
type: BlockTypes.PARAGRAPH, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
li: { | |
type: BlockTypes.LIST_ITEM, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
h1: { | |
type: BlockTypes.HEADLINE, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
h2: { | |
type: BlockTypes.HEADLINE, | |
data: { | |
depth: 2, | |
readOnly: false, | |
}, | |
}, | |
h3: { | |
type: BlockTypes.HEADLINE, | |
data: { | |
depth: 3, | |
readOnly: false, | |
}, | |
}, | |
h4: { | |
type: BlockTypes.HEADLINE, | |
data: { | |
depth: 4, | |
readOnly: false, | |
}, | |
}, | |
h5: { | |
type: BlockTypes.HEADLINE, | |
data: { | |
depth: 5, | |
readOnly: false, | |
}, | |
}, | |
h6: { | |
type: BlockTypes.HEADLINE, | |
data: { | |
depth: 6, | |
readOnly: false, | |
}, | |
}, | |
table: { | |
type: BlockTypes.TABLE, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
th: { | |
type: BlockTypes.TABLE_HEADER_CELL, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
tr: { | |
type: BlockTypes.TABLE_ROW, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
td: { | |
type: BlockTypes.TABLE_CELL, | |
data: { | |
depth: 1, | |
readOnly: false, | |
}, | |
}, | |
}; | |
const RULES = [ | |
{ | |
deserialize(el, next) { | |
let attr = null; | |
if (el && el.getAttribute) { | |
attr = el.getAttribute('parent'); | |
if (attr) { | |
attr = attr.replace(/Block /g, ''); | |
attr = attr.replace(/Map /g, ''); | |
attr = attr.replace(/Character /g, ''); | |
attr = attr.replace(/Set /g, ''); | |
attr = attr.replace(/Mark {/g, ''); | |
attr = attr.replace(/List /g, ''); | |
attr = attr.replace(/Text /g, ''); | |
attr = attr.replace(/} },/g, '},'); | |
attr = attr.replace('[object Object]', '[]'); | |
attr = JSON.parse(attr); | |
} | |
} | |
const block = BLOCK_TAGS[el.tagName.toLowerCase()]; | |
if (!block) return; | |
const build = { | |
kind: 'block', | |
...block, | |
nodes: next(el.childNodes), | |
}; | |
if (attr && attr.type && attr.key) { | |
build.data.parentKey = attr.key; | |
build.data.parentType = attr.type; | |
} | |
return build; | |
}, | |
}, | |
{ | |
deserialize(el, next) { | |
const mark = MARK_TAGS[el.tagName.toLowerCase()]; | |
if (!mark) return; | |
return { | |
kind: 'mark', | |
type: mark, | |
nodes: next(el.childNodes), | |
}; | |
}, | |
}, | |
{ | |
// Special case for code blocks, which need to grab the nested childNodes. | |
deserialize(el, next) { | |
if (el.tagName.toLowerCase() !== 'pre') return; | |
const code = el.childNodes[0]; | |
const childNodes = code && code.tagName.toLowerCase() === 'code' | |
? code.childNodes | |
: el.childNodes; | |
return { | |
kind: 'block', | |
type: 'code', | |
nodes: next(childNodes), | |
}; | |
}, | |
}, | |
{ | |
// Special case for images, to grab their src. | |
deserialize(el, next) { | |
if (el.tagName.toLowerCase() !== 'img') return; | |
return { | |
kind: 'block', | |
type: BlockTypes.IMAGE, | |
isVoid: true, | |
nodes: next(el.childNodes), | |
data: { | |
width: el.getAttribute('width'), | |
height: el.getAttribute('height'), | |
uri: el.getAttribute('src').substring(el.getAttribute('src').indexOf('api/') + 3), | |
}, | |
}; | |
}, | |
}, | |
{ | |
// Special case for links, to grab their href. | |
deserialize(el, next) { | |
if (el.tagName.toLowerCase() !== 'a') return; | |
return { | |
kind: 'inline', | |
type: 'link', | |
nodes: next(el.childNodes), | |
data: { | |
href: el.getAttribute('href'), | |
}, | |
}; | |
}, | |
}, | |
]; | |
/** | |
* Create a new HTML serializer with `RULES`. | |
* | |
* @type {Html} | |
*/ | |
const serializer = new Html({ rules: RULES }); | |
let nodes = []; | |
let lists = []; | |
let listBlock = null; | |
const pasteHandler = (event, change) => { | |
// console.log('onPaste', event, change.value.toJS()); | |
const transfer = getEventTransfer(event); | |
// console.log('!! ', transfer); | |
if (!transfer.html) return; | |
const { document } = serializer.deserialize(transfer.html); | |
document.nodes.forEach((n, idx, arr) => { | |
// console.log('??? ', n); | |
if (n.data.get('parentType') === BlockTypes.UNORDERED_LIST || n.data.get('parentType') === BlockTypes.ORDERED_LIST) { | |
lists.push({ | |
key: n.data.get('parentKey'), | |
type: n.data.get('parentType'), | |
}); | |
} else { | |
if (lists.length > 0) { | |
lists.forEach((l, listindex) => { | |
if (!listBlock) { | |
listBlock = { | |
kind: 'block', | |
type: l.type, | |
nodes: [], | |
}; | |
listBlock.nodes.push(arr.toJS()[listindex]); | |
} else { | |
listBlock.nodes.push(arr.toJS()[listindex]); | |
} | |
}); | |
nodes.push(listBlock); | |
listBlock = null; | |
lists = []; | |
} | |
nodes.push(n.toJS()); | |
} | |
}); | |
if (nodes.length === 0 && lists.length > 0) { | |
lists.forEach((l, listindex) => { | |
if (!listBlock) { | |
listBlock = { | |
kind: 'block', | |
type: l.type, | |
nodes: [], | |
}; | |
listBlock.nodes.push(document.nodes.toJS()[listindex]); | |
} else { | |
listBlock.nodes.push(document.nodes.toJS()[listindex]); | |
} | |
}); | |
nodes.push(listBlock); | |
listBlock = null; | |
lists = []; | |
} | |
nodes.forEach(n => change.insertBlock(Block.create(n))); | |
// change.insertFragment(document); | |
// console.log('>?>>>>> ', document.toJS()); | |
nodes = []; | |
return true; | |
}; | |
export default { | |
onPaste: pasteHandler, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment