diff --git a/shared/editor/lib/uploadPlugin.ts b/shared/editor/lib/uploadPlugin.ts
deleted file mode 100644
index 8d0a0af601..0000000000
--- a/shared/editor/lib/uploadPlugin.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { Plugin } from "prosemirror-state";
-import { getDataTransferFiles } from "../../utils/files";
-import insertFiles, { Options } from "../commands/insertFiles";
-
-const uploadPlugin = (options: Options) =>
- new Plugin({
- props: {
- handleDOMEvents: {
- paste(view, event: ClipboardEvent): boolean {
- if (!view.editable || !options.uploadFile) {
- return false;
- }
-
- if (!event.clipboardData) {
- return false;
- }
-
- // check if we actually pasted any files
- const files = Array.prototype.slice
- .call(event.clipboardData.items)
- .filter((dt: DataTransferItem) => dt.kind !== "string")
- .map((dt: DataTransferItem) => dt.getAsFile())
- .filter(Boolean);
-
- if (files.length === 0) {
- return false;
- }
-
- // When copying from Microsoft Office product the clipboard contains
- // an image version of the content, check if there is also text and
- // use that instead in this scenario.
- const html = event.clipboardData.getData("text/html");
-
- // Fallback to default paste behavior if the clipboard contains HTML
- // Even if there is an image, it's likely to be a screenshot from eg
- // Microsoft Suite / Apple Numbers – and not the original content.
- if (html.length && !html.includes("
response.blob())
+ .then((blob) => {
+ const fileName = fileNameFromUrl(imageSrc) ?? "pasted-image";
+ const ext = extension(blob.type) ?? "png";
+ const name = fileName.endsWith(`.${ext}`)
+ ? fileName
+ : `${fileName}.${ext}`;
+
+ void insertFiles(
+ view,
+ event,
+ result.pos,
+ [
+ new File([blob], name, {
+ type: blob.type,
+ }),
+ ],
+ options
+ );
+ });
+ }
+
+ return false;
+ },
+ },
+ },
+ });
+ }
+}
diff --git a/shared/utils/files.ts b/shared/utils/files.ts
index 02e0119f2a..43873d1a0d 100644
--- a/shared/utils/files.ts
+++ b/shared/utils/files.ts
@@ -25,15 +25,40 @@ export function bytesToHumanReadable(bytes: number | undefined) {
}
/**
- * Get an array of File objects from a drag event
+ * Get an image URL from a drag or clipboard event
*
- * @param event The react or native drag event
- * @returns An array of Files
+ * @param event The event to get the image from.
+ * @returns The URL of the image.
+ */
+export function getDataTransferImage(
+ event: React.DragEvent | DragEvent | ClipboardEvent
+) {
+ const dt =
+ event instanceof ClipboardEvent ? event.clipboardData : event.dataTransfer;
+ const untrustedHTML = dt?.getData("text/html");
+
+ try {
+ return untrustedHTML
+ ? new DOMParser()
+ .parseFromString(untrustedHTML, "text/html")
+ .querySelector("img")?.src
+ : dt?.getData("url");
+ } catch (e) {
+ return;
+ }
+}
+
+/**
+ * Get an array of File objects from a drag or clipboard event
+ *
+ * @param event The event to get files from.
+ * @returns An array of files.
*/
export function getDataTransferFiles(
- event: React.DragEvent | DragEvent
+ event: React.DragEvent | DragEvent | ClipboardEvent
): File[] {
- const dt = event.dataTransfer;
+ const dt =
+ event instanceof ClipboardEvent ? event.clipboardData : event.dataTransfer;
if (dt) {
if ("files" in dt && dt.files.length) {
diff --git a/shared/utils/urls.ts b/shared/utils/urls.ts
index 7e6a5a3c1b..6860539736 100644
--- a/shared/utils/urls.ts
+++ b/shared/utils/urls.ts
@@ -12,6 +12,21 @@ export function cdnPath(path: string): string {
return `${env.CDN_URL ?? ""}${path}`;
}
+/**
+ * Extracts the file name from a given url.
+ *
+ * @param url The url to extract the file name from.
+ * @returns The file name.
+ */
+export function fileNameFromUrl(url: string) {
+ try {
+ const parsed = new URL(url);
+ return parsed.pathname.split("/").pop();
+ } catch (err) {
+ return;
+ }
+}
+
/**
* Returns true if the given string is a link to inside the application.
*
@@ -146,6 +161,12 @@ export function sanitizeUrl(url: string | null | undefined) {
return url;
}
+/**
+ * Returns a regex to match the given url.
+ *
+ * @param url The url to create a regex for.
+ * @returns A regex to match the url.
+ */
export function urlRegex(url: string | null | undefined): RegExp | undefined {
if (!url || !isUrl(url)) {
return undefined;