import { Extension } from '@tiptap/core'
import { Plugin, PluginKey } from 'prosemirror-state'
const mapDataItems = (data, fileMatchRegex) => {
return Array.from(data)
.map(item => (item.type.match(fileMatchRegex) ? item.getAsFile() : null))
.filter(item => item !== null);
};
const mapTextItems = async (data) => {
const fullSet = Array.from(data),
plainText = fullSet.find(item => item.type === 'text/plain'),
richText = fullSet.find(item => item.type === 'text/html');
return new Promise(resolve => {
(richText || plainText).getAsString(html => {
const value = html.replace(/<img[^>]*>/g, '')
resolve(value)
})
})
}
export default Extension.create({
name: 'CustomPasteRules',
addOptions: {
fileMatchRegex: /^image/(gif|jpe?g|a?png|svg|webp|bmp)/i,
disableImagePaste: false
},
addProseMirrorPlugins() {
const options = this.options,
renderer = this.options.render?.();
return [
new Plugin({
key: new PluginKey('imagePasteHandler'),
props: {
handlePaste(_view, event) {
if (options.disableImagePaste && renderer?.['onDisabledImagePaste']) {
mapTextItems(event.clipboardData.items).then(value => {
if (value) {
renderer['onDisabledImagePaste'](value)
}
})
return true
}
if (!options.disableImagePaste && renderer?.['onImagePaste'] && event.clipboardData?.items?.length) {
const files = mapDataItems(event.clipboardData.items, options.fileMatchRegex)
if (files.length) {
renderer['onImagePaste'](files)
return true
}
}
return false
},
handleDrop(_view, event) {
if (!options.disableImagePaste && event.dataTransfer?.files?.length && renderer?.['onImageDrop']) {
const files = mapDataItems(event.dataTransfer.items, options.fileMatchRegex)
if (files.length) {
renderer['onImageDrop'](files)
return true
}
}
return false
}
}
})
]
}
})