@@ -17,6 +17,7 @@ function DropControl(gui, el, cb) {
1717 . on ( 'drop' , ondrop )
1818 . on ( 'paste' , onpaste ) ;
1919 area . node ( ) . addEventListener ( 'paste' , onpaste ) ;
20+ // TODO: use same function for drop and paste
2021 function ondrop ( e ) {
2122 var files = e . dataTransfer . files ;
2223 var types = e . dataTransfer . types ;
@@ -27,7 +28,7 @@ function DropControl(gui, el, cb) {
2728 cb ( e . dataTransfer . getData ( 'text/uri-list' ) . split ( ',' ) ) ;
2829 } else if ( types . includes ( 'text/html' ) ) {
2930 // drag-dropping a highlighted link may pull in a chunk of html
30- var urls = e . dataTransfer . getData ( 'text/html' ) . match ( / h t t p s ? : [ ^ " ' ] + / ) ;
31+ var urls = pastedHtmlToUrls ( e . dataTransfer . getData ( 'text/html' ) ) ;
3132 if ( urls . length ) {
3233 cb ( urls ) ;
3334 }
@@ -36,7 +37,7 @@ function DropControl(gui, el, cb) {
3637 function onpaste ( e ) {
3738 var types = Array . from ( e . clipboardData . types || [ ] ) . join ( ',' ) ;
3839 var items = Array . from ( e . clipboardData . items || [ ] ) ;
39- var files ;
40+ var files , str , urls ;
4041 if ( GUI . textIsSelected ( ) ) {
4142 // user is probably pasting text into an editable text field
4243 return ;
@@ -52,12 +53,22 @@ function DropControl(gui, el, cb) {
5253 // formatted text can be available as both text/plain and text/html (e.g.
5354 // a JSON data object copied from a GitHub issue).
5455 //
56+
57+ // if html is present, it could be data (e.g. from Google Sheets) or a pasted link.
58+ // first we check for a link
59+ if ( types . includes ( 'text/html' ) ) {
60+ urls = pastedHtmlToUrls ( e . clipboardData . getData ( 'text/html' ) ) ;
61+ if ( urls . length ) {
62+ return cb ( urls ) ;
63+ }
64+ }
5565 if ( types . includes ( 'text/plain' ) ) {
5666 // text from clipboard (supported by Chrome, FF, Safari)
5767 // TODO: handle FF case of string containing multiple file names.
58- var str = e . clipboardData . getData ( 'text/plain' ) ;
59- if ( isUrl ( str ) ) {
60- return cb ( str . split ( ',' ) ) ;
68+ str = e . clipboardData . getData ( 'text/plain' ) ;
69+ urls = pastedTextToUrls ( str ) ;
70+ if ( urls . length ) {
71+ return cb ( urls ) ;
6172 }
6273 files = [ pastedTextToFile ( str ) ] ;
6374 } else {
@@ -79,6 +90,21 @@ function DropControl(gui, el, cb) {
7990 }
8091}
8192
93+ function pastedHtmlToUrls ( html ) {
94+ var hrefRegex = / h r e f \s * = \s * [ " ' ] ( [ ^ " ' ] + ) [ " ' ] / gi;
95+ var matches = html . matchAll ( hrefRegex ) ;
96+ var urls = Array . from ( matches , match => match [ 1 ] ) ;
97+ return urls ;
98+ }
99+
100+ function pastedTextToUrls ( str ) {
101+ if ( ! looksLikeUrl ( str ) ) return [ ] ;
102+ var regex = / h t t p s ? : \/ \/ [ ^ \s ] + ?(? = [ \s , ] | $ ) / g;
103+ var matches = str . matchAll ( regex ) ;
104+ var urls = Array . from ( matches , match => match [ 0 ] ) ;
105+ return urls ;
106+ }
107+
82108function pastedTextToFile ( str ) {
83109 var type = internal . guessInputContentType ( str ) ;
84110 var name ;
@@ -93,7 +119,7 @@ function pastedTextToFile(str) {
93119 return new File ( [ blob ] , name ) ;
94120}
95121
96- function isUrl ( str ) {
122+ function looksLikeUrl ( str ) {
97123 return / ^ h t t p s ? : \/ \/ / . test ( str ) ;
98124}
99125
@@ -421,7 +447,7 @@ export function ImportControl(gui, opts) {
421447 function prepFilesForDownload ( names ) {
422448 var items = names . map ( function ( name ) {
423449 var item = { name : name } ;
424- if ( isUrl ( name ) ) {
450+ if ( looksLikeUrl ( name ) ) {
425451 item . url = name ;
426452 item . basename = GUI . getUrlFilename ( name ) ;
427453
0 commit comments