Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@bebbi
Last active February 13, 2019 13:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bebbi/9ba49f2eff018508e57119c3b9c6e582 to your computer and use it in GitHub Desktop.
Save bebbi/9ba49f2eff018508e57119c3b9c6e582 to your computer and use it in GitHub Desktop.
slatejs fragment manipulation for custom onPaste behaviour
import { Block, Document } from 'slate'
import { getEventTransfer } from 'slate-react'
import isContainerNode from '../utils/node/isContainerNode'
/*
* What generalizes about this example is that thanks to slatejs #2589 paste
* behaviour is controlled by the fragment's trunk.
*/
const deepestSingleContainer = doc => {
// result holds the found container.
let result = null
// candidate iterates through fragment.
let candidate = doc
while (
candidate.nodes.size === 1 &&
candidate.nodes.first().object === 'block'
) {
candidate = candidate.nodes.first()
if (isContainerNode(candidate)) {
result = candidate
}
}
return result
}
/*
* Additional benefit, apply custom operations on the pasted fragment such as
* removing id.
* TODO: Simplify? New controller just for this?
*/
const removeUuids = node => {
if (node.object === 'document') {
return Document.create(node.nodes.map(removeUuids))
}
if (node.object !== 'block') {
return node
}
return Block.fromJSON({
...node.toJSON(),
nodes: node.nodes.map(removeUuids),
data: isContainerNode(node) ? node.data.remove('id') : node.data
})
}
/*
* Shorten (or prolong) the fragment's trunk to get a different paste depth.
*/
const truncateFragment = fragment => {
const startBlock = deepestSingleContainer(fragment)
return startBlock ? Document.create([startBlock]) : fragment
}
const onFragment = (event, editor, next) => {
const transfer = getEventTransfer(event)
const { type, fragment } = transfer
if (type !== 'fragment') {
return next()
}
const newFragment = removeUuids(truncateFragment(fragment))
editor.insertFragment(newFragment)
}
export default options => ({
onPaste: onFragment
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment