94 lines
2.2 KiB
JavaScript
94 lines
2.2 KiB
JavaScript
import { Node, Plugin } from 'tiptap'
|
|
|
|
export default class Image extends Node {
|
|
|
|
get name() {
|
|
return 'image'
|
|
}
|
|
|
|
get schema() {
|
|
return {
|
|
inline: true,
|
|
attrs: {
|
|
src: {},
|
|
alt: {
|
|
default: null,
|
|
},
|
|
title: {
|
|
default: null,
|
|
},
|
|
},
|
|
group: 'inline',
|
|
draggable: true,
|
|
parseDOM: [
|
|
{
|
|
tag: 'img[src]',
|
|
getAttrs: dom => ({
|
|
src: dom.getAttribute('src'),
|
|
title: dom.getAttribute('title'),
|
|
alt: dom.getAttribute('alt'),
|
|
}),
|
|
},
|
|
],
|
|
toDOM: node => ['img', node.attrs],
|
|
}
|
|
}
|
|
|
|
commands({ type }) {
|
|
return attrs => (state, dispatch) => {
|
|
const { selection } = state
|
|
const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos
|
|
const node = type.create(attrs)
|
|
const transaction = state.tr.insert(position, node)
|
|
dispatch(transaction)
|
|
}
|
|
}
|
|
|
|
get plugins() {
|
|
return [
|
|
new Plugin({
|
|
props: {
|
|
handleDOMEvents: {
|
|
drop(view, event) {
|
|
const hasFiles = event.dataTransfer
|
|
&& event.dataTransfer.files
|
|
&& event.dataTransfer.files.length
|
|
|
|
if (!hasFiles) {
|
|
return
|
|
}
|
|
|
|
const images = Array
|
|
.from(event.dataTransfer.files)
|
|
.filter(file => (/image/i).test(file.type))
|
|
|
|
if (images.length === 0) {
|
|
return
|
|
}
|
|
|
|
event.preventDefault()
|
|
|
|
const { schema } = view.state
|
|
const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY })
|
|
|
|
images.forEach(image => {
|
|
const reader = new FileReader()
|
|
|
|
reader.onload = readerEvent => {
|
|
const node = schema.nodes.image.create({
|
|
src: readerEvent.target.result,
|
|
})
|
|
const transaction = view.state.tr.insert(coordinates.pos, node)
|
|
view.dispatch(transaction)
|
|
}
|
|
reader.readAsDataURL(image)
|
|
})
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
]
|
|
}
|
|
|
|
}
|