diff --git a/frontend_tests/node_tests/copy_and_paste.js b/frontend_tests/node_tests/copy_and_paste.js
index fbb3c8e87a..c92363617b 100644
--- a/frontend_tests/node_tests/copy_and_paste.js
+++ b/frontend_tests/node_tests/copy_and_paste.js
@@ -1,8 +1,9 @@
global.stub_out_jquery();
set_global('page_params', {
- development: true,
+ development_environment: true,
});
+set_global('compose_ui', {});
const { JSDOM } = require("jsdom");
const { window } = new JSDOM('
Hello world
');
@@ -13,6 +14,25 @@ global.$ = require('jquery')(window);
zrequire('toMarkdown', 'node_modules/to-markdown/dist/to-markdown.js');
var copy_and_paste = zrequire('copy_and_paste');
+// Super stripped down version of the code in the drag-mock library
+// https://github.com/andywer/drag-mock/blob/6d46c7c0ffd6a4d685e6612a90cd58cda80f30fc/src/DataTransfer.js
+var DataTransfer = function () {
+ this.dataByFormat = {};
+};
+DataTransfer.prototype.getData = function (dataFormat) {
+ return this.dataByFormat[dataFormat];
+};
+DataTransfer.prototype.setData = function (dataFormat, data) {
+ this.dataByFormat[dataFormat] = data;
+};
+
+var createPasteEvent = function () {
+ var clipboardData = new DataTransfer();
+ var pasteEvent = new window.Event('paste');
+ pasteEvent.clipboardData = clipboardData;
+ return $.Event(pasteEvent);
+};
+
run_test('paste_handler', () => {
var input = ' love the Zulip Organization.';
@@ -50,4 +70,22 @@ run_test('paste_handler', () => {
input = 'Test List:
';
assert.equal(copy_and_paste.paste_handler_converter(input),
'Test List:\n* Item 1\n* Item 2');
+
+ var data = 'text
';
+ var event = createPasteEvent();
+ event.originalEvent.clipboardData.setData('text/html', data);
+ var insert_syntax_and_focus_called = false;
+ compose_ui.insert_syntax_and_focus = function () {
+ insert_syntax_and_focus_called = true;
+ };
+ copy_and_paste.paste_handler(event);
+ assert(insert_syntax_and_focus_called);
+
+ data = '
';
+ event = createPasteEvent();
+ event.originalEvent.clipboardData.setData('text/html', data);
+ insert_syntax_and_focus_called = false;
+ copy_and_paste.paste_handler(event);
+ assert(!insert_syntax_and_focus_called);
+
});
diff --git a/static/js/copy_and_paste.js b/static/js/copy_and_paste.js
index c5304c3d47..9a361042d3 100644
--- a/static/js/copy_and_paste.js
+++ b/static/js/copy_and_paste.js
@@ -235,8 +235,16 @@ exports.paste_handler = function (event) {
if (clipboardData.getData) {
var paste_html = clipboardData.getData('text/html');
if (paste_html && page_params.development_environment) {
- event.preventDefault();
var text = exports.paste_handler_converter(paste_html);
+ var mdImageRegex = /^!\[.*\]\(.*\)$/;
+ if (text.match(mdImageRegex)) {
+ // This block catches cases where we are pasting an
+ // image into Zulip, which should be handled by the
+ // jQuery filedrop library, not this code path.
+ return;
+ }
+ event.preventDefault();
+ event.stopPropagation();
compose_ui.insert_syntax_and_focus(text);
}
}
diff --git a/static/third/jquery-filedrop/jquery.filedrop.js b/static/third/jquery-filedrop/jquery.filedrop.js
index 35503c7ac8..6a3e2ed875 100644
--- a/static/third/jquery-filedrop/jquery.filedrop.js
+++ b/static/third/jquery-filedrop/jquery.filedrop.js
@@ -164,22 +164,52 @@
sendRawImageData(event, image);
}
+ function dataIsImage(data) {
+ // Check if the clipboard data is actually an image or a thumbnail of the
+ // copied text.
+
+ var text = data.getData('text/html');
+
+ if (!text) {
+ // No html is present, when pasting from image viewers or a screenshot
+ return true;
+ }
+
+ try {
+ var html = $.parseHTML(text);
+ } catch(e) {
+ // This is really a problem with the software, where we copied the text
+ // from - but we just let the default browser behavior prevail
+ return false;
+ }
+
+ // Some software like MS Word adds an image thumbnail, when text is
+ // copied. We would like to paste the actual text, instead of the
+ // thumbnail image in this case.
+
+ // When an image copied in a (modern?) Browser, a 'text/html' item is
+ // present in the clipboard, which has an img tag for the copied image
+ // (along with may be a meta tag)
+
+ var allowedTags = ["META", "IMG"];
+ for (var i=0; i < html.length; i += 1){
+ if (allowedTags.indexOf(html[i].nodeName) < 0){
+ return false;
+ }
+ }
+ return true;
+ }
+
function paste(event) {
if (event.originalEvent.clipboardData === undefined ||
event.originalEvent.clipboardData.items === undefined) {
return;
}
- // Check if any of the items are strings, and if they are,
- // then return, since we want the default browser behavior
- // to deal with those.
-
- var itemsLength = event.originalEvent.clipboardData.items.length;
-
- for (var i = 0; i < itemsLength; i++) {
- if (event.originalEvent.clipboardData.items[i].kind === "string") {
- return;
- }
+ // Check if the data in the clipboard is really an image, or just a
+ // thumbnail of the copied text.
+ if (!dataIsImage(event.originalEvent.clipboardData)){
+ return;
}
// Take the first image pasted in the clipboard