@@ -32,9 +32,11 @@ export const keybindings = {
3232 "Meta+c" : "Copy" ,
3333 "Ctrl+x" : "Cut" ,
3434 "Meta+x" : "Cut" ,
35- "Ctrl+v" : "Paste" ,
3635 "Ctrl+Shift+v" : "Paste values" ,
37- "Meta+v" : "Paste" ,
36+ // Disabled here because we handle paste event instead
37+ // TODO: Handle these keybindings only if no paste event is fired
38+ // "Ctrl+v": "Paste",
39+ // "Meta+v": "Paste",
3840 "Meta+Shift+v" : "Paste values" ,
3941 p : "Put After" ,
4042 "Shift+p" : "Put Before" ,
@@ -81,14 +83,33 @@ export const keybindings = {
8183 // gT and gt
8284} ;
8385
84- async function getClipboard ( ) {
85- let clipboard = await navigator . clipboard . read ( ) ;
86+ async function getClipboard ( e ) {
8687 const types = { } ;
87- for ( const item of clipboard ) {
88- for ( const type of item . types ) {
89- if ( type in types || ! type . startsWith ( "text/" ) ) continue ;
90- const blob = await item . getType ( type ) ;
91- types [ type ] = await blob . text ( ) ;
88+ const dataTransfer = e . dataTransfer ?? e . clipboardData ;
89+ if ( dataTransfer != null ) {
90+ await Promise . all (
91+ Array . from ( dataTransfer . items ) . map (
92+ ( item ) =>
93+ new Promise ( ( resolve ) => {
94+ if ( item . kind != "string" ) return resolve ( ) ;
95+ item . getAsString ( ( s ) => {
96+ if ( item . type in types || ! item . type . startsWith ( "text/" ) ) {
97+ return resolve ( ) ;
98+ }
99+ types [ item . type ] = s ;
100+ resolve ( ) ;
101+ } ) ;
102+ } ) ,
103+ ) ,
104+ ) ;
105+ } else {
106+ let clipboard = await navigator . clipboard . read ( ) ;
107+ for ( const item of clipboard ) {
108+ for ( const type of item . types ) {
109+ if ( type in types || ! type . startsWith ( "text/" ) ) continue ;
110+ const blob = await item . getType ( type ) ;
111+ types [ type ] = await blob . text ( ) ;
112+ }
92113 }
93114 }
94115 return types ;
@@ -131,10 +152,12 @@ function setPasteBufferFromClipboard(globals, clipboard) {
131152 globals . pasteBuffer = new Register (
132153 type ,
133154 Array . from ( table . querySelectorAll ( "tr" ) ) . map ( ( row ) =>
134- Array . from ( row . querySelectorAll ( "td" ) ) . map (
155+ Array . from ( row . querySelectorAll ( "td, th " ) ) . map (
135156 ( { dataset : { formula } , innerText : value } ) => ( {
136- formula : formula != "" ? formula : undefined ,
137- get : ( ) => ( value != "" ? value : undefined ) ,
157+ formula :
158+ formula || ( value != "" && value != null ? value : undefined ) ,
159+ // Values can be zero, so we have to explicitly check falsy cases
160+ get : ( ) => ( value != "" && value != null ? value : undefined ) ,
138161 } ) ,
139162 ) ,
140163 ) ,
@@ -242,13 +265,13 @@ export const actions = {
242265
243266 Paste : async ( e , globals ) => {
244267 // TODO: Notify the user of paste error
245- setPasteBufferFromClipboard ( globals , await getClipboard ( ) ) ;
268+ setPasteBufferFromClipboard ( globals , await getClipboard ( e ) ) ;
246269 return actions [ "Put After" ] ( e , globals ) ;
247270 } ,
248271
249272 "Paste values" : async ( e , globals ) => {
250273 // TODO: Notify the user of paste error
251- setPasteBufferFromClipboard ( globals , await getClipboard ( ) ) ;
274+ setPasteBufferFromClipboard ( globals , await getClipboard ( e ) ) ;
252275 switch ( globals . mode ) {
253276 case "normal" :
254277 case "visual" :
0 commit comments