diff --git a/src/trix/controllers/level_2_input_controller.js b/src/trix/controllers/level_2_input_controller.js index a83cf6760..c6a674bce 100644 --- a/src/trix/controllers/level_2_input_controller.js +++ b/src/trix/controllers/level_2_input_controller.js @@ -363,7 +363,6 @@ export default class Level2InputController extends InputController { const href = dataTransfer.getData("URL") const html = dataTransfer.getData("text/html") - const file = dataTransfer.files?.[0] if (href) { let string @@ -394,9 +393,9 @@ export default class Level2InputController extends InputController { this.afterRender = () => { return this.delegate?.inputControllerDidPaste(paste) } - } else if (file && !dataTransferIsMsOfficePaste(dataTransfer)) { + } else if (processableFilePaste(this.event)) { paste.type = "File" - paste.file = file + paste.file = dataTransfer.files[0] this.delegate?.inputControllerWillPaste(paste) this.withTargetDOMRange(function() { return this.responder?.insertFile(paste.file) @@ -582,10 +581,20 @@ const staticRangeToRange = function(staticRange) { const dragEventHasFiles = (event) => Array.from(event.dataTransfer?.types || []).includes("Files") +const processableFilePaste = (event) => { + // Paste events that only have files are handled by the paste event handler, + // to work around Safari not supporting beforeinput.insertFromPaste for files. + + // MS Office text pastes include a file with a screenshot of the text, but we should + // handle them as text pastes. + return event.dataTransfer.files?.[0] && !pasteEventHasFilesOnly(event) && !dataTransferIsMsOfficePaste(event) +} + const pasteEventHasFilesOnly = function(event) { const clipboard = event.clipboardData if (clipboard) { - return clipboard.types.includes("Files") && clipboard.types.length === 1 && clipboard.files.length >= 1 + const fileTypes = Array.from(clipboard.types).filter((type) => type.match(/file/i)) // "Files", "application/x-moz-file" + return fileTypes.length === clipboard.types.length && clipboard.files.length >= 1 } } diff --git a/src/trix/core/helpers/events.js b/src/trix/core/helpers/events.js index 0565a608d..4248830d3 100644 --- a/src/trix/core/helpers/events.js +++ b/src/trix/core/helpers/events.js @@ -14,7 +14,7 @@ export const dataTransferIsPlainText = function(dataTransfer) { } } -export const dataTransferIsMsOfficePaste = function(dataTransfer) { +export const dataTransferIsMsOfficePaste = ({ dataTransfer }) => { return dataTransfer.types.includes("Files") && dataTransfer.types.includes("text/html") && dataTransfer.getData("text/html").includes("urn:schemas-microsoft-com:office:office")