Implement cut/copy correctly for input/textarea elements

This commit is contained in:
Scott Nonnenberg 2023-06-06 12:06:58 -07:00 committed by GitHub
parent 82419f17dd
commit adc8513f41
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 3 deletions

View file

@ -9,6 +9,19 @@ export function createEventHandler({
deleteSelection: boolean;
}) {
return (event: ClipboardEvent): void => {
// If we're attempting to cut, and focus is not in one of our composer elements, we
// let the browser do its default behavior. We don't need formatting from them.
if (deleteSelection) {
const { activeElement } = document;
if (
!activeElement ||
activeElement.matches('input, textarea') ||
!activeElement.closest('[contenteditable=true]')
) {
return;
}
}
if (!event.clipboardData) {
return;
}
@ -25,9 +38,11 @@ export function createEventHandler({
container.appendChild(range.cloneContents());
}
// We fail over to selection.toString() because we can't pull values from the DOM if
// the selection is within an <input/> or <textarea/>. But the browser can!
const plaintext = getStringFromNode(container) || selection.toString();
// Note: we can't leave text/plain alone and just add text/signal; if we update
// clipboardData at all, all other data is reset.
const plaintext = getStringFromNode(container);
event.clipboardData?.setData('text/plain', plaintext);
event.clipboardData?.setData('text/signal', container.innerHTML);

View file

@ -2555,9 +2555,9 @@
{
"rule": "DOM-innerHTML",
"path": "ts/quill/signal-clipboard/util.ts",
"line": " event.clipboardData?.setData('text/signal', container.innerHTML);",
"line": " event.clipboardData?.setData('text/signal', container.innerHTML);",
"reasonCategory": "regexMatchedSafeCode",
"updated": "2023-05-22T23:45:02.074Z",
"updated": "2023-06-02T00:37:19.861Z",
"reasonDetail": "Reading from innerHTML, not setting it"
},
{