|
| 1 | +import type { BlockNoteEditor } from "../../editor/BlockNoteEditor"; |
| 2 | +import { PartialBlock } from "../../blocks/defaultBlocks"; |
| 3 | +import { insertOrUpdateBlock } from "../../extensions/SuggestionMenu/getDefaultSlashMenuItems"; |
| 4 | +import { |
| 5 | + BlockSchema, |
| 6 | + FileBlockConfig, |
| 7 | + InlineContentSchema, |
| 8 | + StyleSchema, |
| 9 | +} from "../../schema"; |
| 10 | +import { acceptedMIMETypes } from "./acceptedMIMETypes"; |
| 11 | + |
| 12 | +function checkMIMETypesMatch(mimeType1: string, mimeType2: string) { |
| 13 | + const types1 = mimeType1.split("/"); |
| 14 | + const types2 = mimeType2.split("/"); |
| 15 | + |
| 16 | + if (types1.length !== 2) { |
| 17 | + throw new Error(`The string ${mimeType1} is not a valid MIME type.`); |
| 18 | + } |
| 19 | + if (types2.length !== 2) { |
| 20 | + throw new Error(`The string ${mimeType2} is not a valid MIME type.`); |
| 21 | + } |
| 22 | + |
| 23 | + if (types1[1] === "*" || types2[1] === "*") { |
| 24 | + return types1[0] === types2[0]; |
| 25 | + } |
| 26 | + if (types1[0] === "*" || types2[0] === "*") { |
| 27 | + return types1[1] === types2[1]; |
| 28 | + } |
| 29 | + |
| 30 | + return types1[0] === types2[0] && types1[1] === types2[1]; |
| 31 | +} |
| 32 | + |
| 33 | +export async function handleFileInsertion< |
| 34 | + BSchema extends BlockSchema, |
| 35 | + I extends InlineContentSchema, |
| 36 | + S extends StyleSchema |
| 37 | +>(event: DragEvent | ClipboardEvent, editor: BlockNoteEditor<BSchema, I, S>) { |
| 38 | + if (!editor.uploadFile) { |
| 39 | + return; |
| 40 | + } |
| 41 | + |
| 42 | + const dataTransfer = |
| 43 | + "dataTransfer" in event ? event.dataTransfer : event.clipboardData; |
| 44 | + if (dataTransfer === null) { |
| 45 | + return; |
| 46 | + } |
| 47 | + |
| 48 | + let format: (typeof acceptedMIMETypes)[number] | null = null; |
| 49 | + for (const mimeType of acceptedMIMETypes) { |
| 50 | + if (dataTransfer.types.includes(mimeType)) { |
| 51 | + format = mimeType; |
| 52 | + break; |
| 53 | + } |
| 54 | + } |
| 55 | + if (format !== "Files") { |
| 56 | + return; |
| 57 | + } |
| 58 | + |
| 59 | + const items = dataTransfer.items; |
| 60 | + if (!items) { |
| 61 | + return; |
| 62 | + } |
| 63 | + |
| 64 | + event.preventDefault(); |
| 65 | + |
| 66 | + const fileBlockConfigs = Object.values(editor.schema.blockSchema).filter( |
| 67 | + (blockConfig) => blockConfig.isFileBlock |
| 68 | + ) as FileBlockConfig[]; |
| 69 | + |
| 70 | + for (let i = 0; i < items.length; i++) { |
| 71 | + // Gets file block corresponding to MIME type. |
| 72 | + let fileBlockType = "file"; |
| 73 | + for (const fileBlockConfig of fileBlockConfigs) { |
| 74 | + for (const mimeType of fileBlockConfig.fileBlockAcceptMimeTypes || []) { |
| 75 | + if (checkMIMETypesMatch(items[i].type, mimeType)) { |
| 76 | + fileBlockType = fileBlockConfig.type; |
| 77 | + break; |
| 78 | + } |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + const file = items[i].getAsFile(); |
| 83 | + if (file) { |
| 84 | + const updateData = await editor.uploadFile(file); |
| 85 | + |
| 86 | + if (typeof updateData === "string") { |
| 87 | + const fileBlock = { |
| 88 | + type: fileBlockType, |
| 89 | + props: { |
| 90 | + name: file.name, |
| 91 | + url: updateData, |
| 92 | + }, |
| 93 | + } as PartialBlock<BSchema, I, S>; |
| 94 | + |
| 95 | + insertOrUpdateBlock(editor, fileBlock); |
| 96 | + } |
| 97 | + } |
| 98 | + } |
| 99 | +} |
0 commit comments