diff --git a/web/src/copy_and_paste.js b/web/src/copy_and_paste.js index 37d0965abd..ce186a5369 100644 --- a/web/src/copy_and_paste.js +++ b/web/src/copy_and_paste.js @@ -322,6 +322,16 @@ function within_single_element(html_fragment) { ); } +export function is_white_space_pre(paste_html) { + const html_fragment = new DOMParser() + .parseFromString(paste_html, "text/html") + .querySelector("body"); + return ( + within_single_element(html_fragment) && + html_fragment.firstElementChild.style.whiteSpace === "pre" + ); +} + export function paste_handler_converter(paste_html) { const copied_html_fragment = new DOMParser() .parseFromString(paste_html, "text/html") @@ -563,7 +573,7 @@ export function paste_handler(event) { if (clipboardData.getData) { const $textarea = $(event.currentTarget); const paste_text = clipboardData.getData("text"); - const paste_html = clipboardData.getData("text/html"); + let paste_html = clipboardData.getData("text/html"); // Trim the paste_text to accommodate sloppy copying const trimmed_paste_text = paste_text.trim(); @@ -589,6 +599,12 @@ export function paste_handler(event) { ) { event.preventDefault(); event.stopPropagation(); + if (is_white_space_pre(paste_html)) { + // Copied content styled with `white-space: pre` is pasted as is + // but formatted as code. We need this for content copied from + // VS Code like sources. + paste_html = "
" + paste_text + "
";
+ }
const text = paste_handler_converter(paste_html);
compose_ui.insert_and_scroll_into_view(text, $textarea);
}
diff --git a/web/tests/copy_and_paste.test.js b/web/tests/copy_and_paste.test.js
index 1e2185b308..340778adeb 100644
--- a/web/tests/copy_and_paste.test.js
+++ b/web/tests/copy_and_paste.test.js
@@ -8,6 +8,16 @@ const {page_params} = require("./lib/zpage_params");
const copy_and_paste = zrequire("copy_and_paste");
+run_test("is_white_space_pre", () => {
+ // Copied HTML from VS Code
+ let paste_html = `