mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
* wip * wip page * chore: style * wip pages * wip pages * chore: toggle * chore: link * feat: topic search * chore: page section * refactor: apply tailwind class ordering * fix: handle loggedIn user for guest route * feat: folder & image schema * chore: move utils to shared * refactor: tailwind class ordering * feat: img ext for editor * refactor: remove qa * fix: tanstack start * fix: wrong import * chore: use toast * chore: schema
117 lines
2.7 KiB
TypeScript
117 lines
2.7 KiB
TypeScript
import { type Editor, Extension } from "@tiptap/core"
|
|
import { Plugin, PluginKey } from "@tiptap/pm/state"
|
|
import type { FileError, FileValidationOptions } from "@shared/editor/lib/utils"
|
|
import { filterFiles } from "@shared/editor/lib/utils"
|
|
|
|
type FileHandlePluginOptions = {
|
|
key?: PluginKey
|
|
editor: Editor
|
|
onPaste?: (editor: Editor, files: File[], pasteContent?: string) => void
|
|
onDrop?: (editor: Editor, files: File[], pos: number) => void
|
|
onValidationError?: (errors: FileError[]) => void
|
|
} & FileValidationOptions
|
|
|
|
const FileHandlePlugin = (options: FileHandlePluginOptions) => {
|
|
const {
|
|
key,
|
|
editor,
|
|
onPaste,
|
|
onDrop,
|
|
onValidationError,
|
|
allowedMimeTypes,
|
|
maxFileSize,
|
|
} = options
|
|
|
|
return new Plugin({
|
|
key: key || new PluginKey("fileHandler"),
|
|
|
|
props: {
|
|
handleDrop(view, event) {
|
|
event.preventDefault()
|
|
event.stopPropagation()
|
|
|
|
const { dataTransfer } = event
|
|
|
|
if (!dataTransfer?.files.length) {
|
|
return
|
|
}
|
|
|
|
const pos = view.posAtCoords({
|
|
left: event.clientX,
|
|
top: event.clientY,
|
|
})
|
|
|
|
const [validFiles, errors] = filterFiles(
|
|
Array.from(dataTransfer.files),
|
|
{
|
|
allowedMimeTypes,
|
|
maxFileSize,
|
|
allowBase64: options.allowBase64,
|
|
},
|
|
)
|
|
|
|
if (errors.length > 0 && onValidationError) {
|
|
onValidationError(errors)
|
|
}
|
|
|
|
if (validFiles.length > 0 && onDrop) {
|
|
onDrop(editor, validFiles, pos?.pos ?? 0)
|
|
}
|
|
},
|
|
|
|
handlePaste(_, event) {
|
|
event.preventDefault()
|
|
event.stopPropagation()
|
|
|
|
const { clipboardData } = event
|
|
|
|
if (!clipboardData?.files.length) {
|
|
return
|
|
}
|
|
|
|
const [validFiles, errors] = filterFiles(
|
|
Array.from(clipboardData.files),
|
|
{
|
|
allowedMimeTypes,
|
|
maxFileSize,
|
|
allowBase64: options.allowBase64,
|
|
},
|
|
)
|
|
const html = clipboardData.getData("text/html")
|
|
|
|
if (errors.length > 0 && onValidationError) {
|
|
onValidationError(errors)
|
|
}
|
|
|
|
if (validFiles.length > 0 && onPaste) {
|
|
onPaste(editor, validFiles, html)
|
|
}
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
export const FileHandler = Extension.create<
|
|
Omit<FileHandlePluginOptions, "key" | "editor">
|
|
>({
|
|
name: "fileHandler",
|
|
|
|
addOptions() {
|
|
return {
|
|
allowBase64: false,
|
|
allowedMimeTypes: [],
|
|
maxFileSize: 0,
|
|
}
|
|
},
|
|
|
|
addProseMirrorPlugins() {
|
|
return [
|
|
FileHandlePlugin({
|
|
key: new PluginKey(this.name),
|
|
editor: this.editor,
|
|
...this.options,
|
|
}),
|
|
]
|
|
},
|
|
})
|