Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore images from embedded html when pasting, paste plaintext instead. #21476

Merged
50 changes: 14 additions & 36 deletions src/components/Composer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
import RNTextInput from '../RNTextInput';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import Growl from '../../libs/Growl';

Check failure on line 8 in src/components/Composer/index.js

View workflow job for this annotation

GitHub Actions / lint

'Growl' is defined but never used
import themeColors from '../../styles/themes/default';
import updateIsFullComposerAvailable from '../../libs/ComposerUtils/updateIsFullComposerAvailable';
import * as ComposerUtils from '../../libs/ComposerUtils';
Expand Down Expand Up @@ -112,7 +112,7 @@
checkComposerVisibility: () => false,
};

const IMAGE_EXTENSIONS = {

Check failure on line 115 in src/components/Composer/index.js

View workflow job for this annotation

GitHub Actions / lint

'IMAGE_EXTENSIONS' is assigned a value but never used
'image/bmp': 'bmp',
'image/gif': 'gif',
'image/jpeg': 'jpg',
Expand Down Expand Up @@ -300,6 +300,16 @@
this.paste(parser.htmlToMarkdown(html));
}

/**
* Paste the plaintext content into Composer.
*
* @param {ClipboardEvent} event
*/
handlePastePlainText(event) {
const plainText = event.clipboardData.getData('text/plain');
this.paste(plainText);
}

/**
* Check the paste event for an attachment, parse the data and call onPasteFile from props with the selected file,
* Otherwise, convert pasted HTML to Markdown and set it on the composer.
Expand Down Expand Up @@ -337,52 +347,20 @@
const domparser = new DOMParser();
const embeddedImages = domparser.parseFromString(pastedHTML, TEXT_HTML).images;

// If HTML has img tag, then fetch images from it.
// Exclude parsing img tags in the HTML, as fetching the image via fetch triggers a Content-Security-Policy error.
techievivek marked this conversation as resolved.
Show resolved Hide resolved
qispark marked this conversation as resolved.
Show resolved Hide resolved
if (embeddedImages.length > 0 && embeddedImages[0].src) {
// If HTML has emoji, then treat this as plain text.
if (embeddedImages[0].dataset && embeddedImages[0].dataset.stringifyType === 'emoji') {
const plainText = event.clipboardData.getData('text/plain');
this.paste(plainText);
return;
this.handlePastePlainText(event);
return;
}
fetch(embeddedImages[0].src)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.blob();
})
.then((x) => {
const extension = IMAGE_EXTENSIONS[x.type];
if (!extension) {
throw new Error(this.props.translate('composer.noExtensionFoundForMimeType'));
}

return new File([x], `pasted_image.${extension}`, {});
})
.then(this.props.onPasteFile)
.catch(() => {
const errorDesc = this.props.translate('composer.problemGettingImageYouPasted');
Growl.error(errorDesc);

/*
* Since we intercepted the user-triggered paste event to check for attachments,
* we need to manually set the value and call the `onChangeText` handler.
* Synthetically-triggered paste events do not affect the document's contents.
* See https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event for more details.
*/
this.handlePastedHTML(pastedHTML);
});
return;
}

this.handlePastedHTML(pastedHTML);
return;
}

const plainText = event.clipboardData.getData('text/plain');

this.paste(plainText);
this.handlePastePlainText(event);
}

/**
Expand Down
Loading