@@ -32,9 +32,11 @@ export const keybindings = {
32
32
"Meta+c" : "Copy" ,
33
33
"Ctrl+x" : "Cut" ,
34
34
"Meta+x" : "Cut" ,
35
- "Ctrl+v" : "Paste" ,
36
35
"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",
38
40
"Meta+Shift+v" : "Paste values" ,
39
41
p : "Put After" ,
40
42
"Shift+p" : "Put Before" ,
@@ -81,14 +83,33 @@ export const keybindings = {
81
83
// gT and gt
82
84
} ;
83
85
84
- async function getClipboard ( ) {
85
- let clipboard = await navigator . clipboard . read ( ) ;
86
+ async function getClipboard ( e ) {
86
87
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
+ }
92
113
}
93
114
}
94
115
return types ;
@@ -131,10 +152,12 @@ function setPasteBufferFromClipboard(globals, clipboard) {
131
152
globals . pasteBuffer = new Register (
132
153
type ,
133
154
Array . from ( table . querySelectorAll ( "tr" ) ) . map ( ( row ) =>
134
- Array . from ( row . querySelectorAll ( "td" ) ) . map (
155
+ Array . from ( row . querySelectorAll ( "td, th " ) ) . map (
135
156
( { 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 ) ,
138
161
} ) ,
139
162
) ,
140
163
) ,
@@ -242,13 +265,13 @@ export const actions = {
242
265
243
266
Paste : async ( e , globals ) => {
244
267
// TODO: Notify the user of paste error
245
- setPasteBufferFromClipboard ( globals , await getClipboard ( ) ) ;
268
+ setPasteBufferFromClipboard ( globals , await getClipboard ( e ) ) ;
246
269
return actions [ "Put After" ] ( e , globals ) ;
247
270
} ,
248
271
249
272
"Paste values" : async ( e , globals ) => {
250
273
// TODO: Notify the user of paste error
251
- setPasteBufferFromClipboard ( globals , await getClipboard ( ) ) ;
274
+ setPasteBufferFromClipboard ( globals , await getClipboard ( e ) ) ;
252
275
switch ( globals . mode ) {
253
276
case "normal" :
254
277
case "visual" :
0 commit comments