handsontable 0.0.0-next-cecf979-20231026 → 0.0.0-next-e54c3d6-20231026
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of handsontable might be problematic. Click here for more details.
- package/3rdparty/walkontable/src/cell/coords.d.ts +2 -0
- package/3rdparty/walkontable/src/cell/coords.js +29 -0
- package/3rdparty/walkontable/src/cell/coords.mjs +29 -0
- package/base.js +2 -2
- package/base.mjs +2 -2
- package/core/focusCatcher/index.js +26 -20
- package/core/focusCatcher/index.mjs +26 -20
- package/core.js +65 -53
- package/core.mjs +65 -53
- package/dist/handsontable.css +2 -2
- package/dist/handsontable.full.css +2 -2
- package/dist/handsontable.full.js +3602 -2219
- package/dist/handsontable.full.min.css +2 -2
- package/dist/handsontable.full.min.js +88 -81
- package/dist/handsontable.js +3603 -2220
- package/dist/handsontable.min.css +2 -2
- package/dist/handsontable.min.js +30 -23
- package/helpers/mixed.js +1 -1
- package/helpers/mixed.mjs +1 -1
- package/package.json +1 -1
- package/pluginHooks.d.ts +30 -6
- package/pluginHooks.js +148 -62
- package/pluginHooks.mjs +148 -62
- package/plugins/copyPaste/clipboardData/clipboardData.js +517 -0
- package/plugins/copyPaste/clipboardData/clipboardData.mjs +512 -0
- package/plugins/copyPaste/clipboardData/copyClipboardData.js +69 -0
- package/plugins/copyPaste/clipboardData/copyClipboardData.mjs +65 -0
- package/plugins/copyPaste/clipboardData/index.js +9 -0
- package/plugins/copyPaste/clipboardData/index.mjs +4 -0
- package/plugins/copyPaste/clipboardData/pasteClipboardData.js +81 -0
- package/plugins/copyPaste/clipboardData/pasteClipboardData.mjs +77 -0
- package/plugins/copyPaste/copyPaste.js +38 -92
- package/plugins/copyPaste/copyPaste.mjs +40 -94
- package/plugins/nestedHeaders/nestedHeaders.js +21 -22
- package/plugins/nestedHeaders/nestedHeaders.mjs +21 -22
- package/selection/selection.js +12 -0
- package/selection/selection.mjs +12 -0
- package/selection/transformation.js +42 -44
- package/selection/transformation.mjs +42 -44
- package/shortcutContexts/grid.js +4 -0
- package/shortcutContexts/grid.mjs +4 -0
- package/utils/parseTable.js +527 -83
- package/utils/parseTable.mjs +523 -82
- package/plugins/copyPaste/clipboardData.js +0 -18
- package/plugins/copyPaste/clipboardData.mjs +0 -14
- package/plugins/copyPaste/pasteEvent.js +0 -14
- package/plugins/copyPaste/pasteEvent.mjs +0 -9
@@ -0,0 +1,81 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
exports.__esModule = true;
|
4
|
+
require("core-js/modules/es.error.cause.js");
|
5
|
+
var _clipboardData = require("./clipboardData");
|
6
|
+
var _parseTable = require("../../../utils/parseTable");
|
7
|
+
var _SheetClip = require("../../../3rdparty/SheetClip");
|
8
|
+
var _mixed = require("../../../helpers/mixed");
|
9
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
10
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
11
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
12
|
+
/**
|
13
|
+
* Creates an object containing information about paste action.
|
14
|
+
*
|
15
|
+
* @private
|
16
|
+
*/
|
17
|
+
class PasteClipboardData extends _clipboardData.ClipboardData {
|
18
|
+
/**
|
19
|
+
* @param {string} data Data of "text/plain" type inside the clipboard.
|
20
|
+
* @param {string} html Sanitized data of "text/html" type inside the clipboard.
|
21
|
+
*/
|
22
|
+
constructor(data, html) {
|
23
|
+
super();
|
24
|
+
/**
|
25
|
+
* Sanitized data of "text/html" type inside the clipboard.
|
26
|
+
*
|
27
|
+
* @private
|
28
|
+
* @type {string}
|
29
|
+
*/
|
30
|
+
_defineProperty(this, "html", void 0);
|
31
|
+
/**
|
32
|
+
* Copied data stored as array of arrays.
|
33
|
+
*
|
34
|
+
* @private
|
35
|
+
* @type {string[][]}
|
36
|
+
*/
|
37
|
+
_defineProperty(this, "data", void 0);
|
38
|
+
this.html = html;
|
39
|
+
if (this.isSerializedTable()) {
|
40
|
+
this.data = (0, _parseTable.getDataWithHeadersByConfig)(this.getMetaInfo());
|
41
|
+
} else {
|
42
|
+
this.data = (0, _SheetClip.parse)(data);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Checks whether pasted data is an array.
|
48
|
+
*
|
49
|
+
* @private
|
50
|
+
* @returns {boolean}
|
51
|
+
*/
|
52
|
+
isSerializedTable() {
|
53
|
+
return (0, _mixed.isDefined)(this.html) && /(<table)|(<TABLE)/g.test(this.html);
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Checks whether pasted data is a Handsontable.
|
58
|
+
*
|
59
|
+
* @private
|
60
|
+
* @returns {boolean}
|
61
|
+
*/
|
62
|
+
isSerializedHandsontable() {
|
63
|
+
return this.isSerializedTable() && /<meta (.*?)content="Handsontable"/.test(this.html);
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Gets type of the copied data.
|
68
|
+
*
|
69
|
+
* @returns {'table' | 'handsontable' | 'unrecognizable'}
|
70
|
+
*/
|
71
|
+
getType() {
|
72
|
+
if (this.isSerializedHandsontable()) {
|
73
|
+
return 'handsontable';
|
74
|
+
}
|
75
|
+
if (this.isSerializedTable()) {
|
76
|
+
return 'table';
|
77
|
+
}
|
78
|
+
return 'unrecognizable';
|
79
|
+
}
|
80
|
+
}
|
81
|
+
exports.PasteClipboardData = PasteClipboardData;
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import "core-js/modules/es.error.cause.js";
|
2
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
3
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
4
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
5
|
+
import { ClipboardData } from "./clipboardData.mjs";
|
6
|
+
import { getDataWithHeadersByConfig } from "../../../utils/parseTable.mjs";
|
7
|
+
import { parse } from "../../../3rdparty/SheetClip/index.mjs";
|
8
|
+
import { isDefined } from "../../../helpers/mixed.mjs";
|
9
|
+
/**
|
10
|
+
* Creates an object containing information about paste action.
|
11
|
+
*
|
12
|
+
* @private
|
13
|
+
*/
|
14
|
+
export class PasteClipboardData extends ClipboardData {
|
15
|
+
/**
|
16
|
+
* @param {string} data Data of "text/plain" type inside the clipboard.
|
17
|
+
* @param {string} html Sanitized data of "text/html" type inside the clipboard.
|
18
|
+
*/
|
19
|
+
constructor(data, html) {
|
20
|
+
super();
|
21
|
+
/**
|
22
|
+
* Sanitized data of "text/html" type inside the clipboard.
|
23
|
+
*
|
24
|
+
* @private
|
25
|
+
* @type {string}
|
26
|
+
*/
|
27
|
+
_defineProperty(this, "html", void 0);
|
28
|
+
/**
|
29
|
+
* Copied data stored as array of arrays.
|
30
|
+
*
|
31
|
+
* @private
|
32
|
+
* @type {string[][]}
|
33
|
+
*/
|
34
|
+
_defineProperty(this, "data", void 0);
|
35
|
+
this.html = html;
|
36
|
+
if (this.isSerializedTable()) {
|
37
|
+
this.data = getDataWithHeadersByConfig(this.getMetaInfo());
|
38
|
+
} else {
|
39
|
+
this.data = parse(data);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Checks whether pasted data is an array.
|
45
|
+
*
|
46
|
+
* @private
|
47
|
+
* @returns {boolean}
|
48
|
+
*/
|
49
|
+
isSerializedTable() {
|
50
|
+
return isDefined(this.html) && /(<table)|(<TABLE)/g.test(this.html);
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Checks whether pasted data is a Handsontable.
|
55
|
+
*
|
56
|
+
* @private
|
57
|
+
* @returns {boolean}
|
58
|
+
*/
|
59
|
+
isSerializedHandsontable() {
|
60
|
+
return this.isSerializedTable() && /<meta (.*?)content="Handsontable"/.test(this.html);
|
61
|
+
}
|
62
|
+
|
63
|
+
/**
|
64
|
+
* Gets type of the copied data.
|
65
|
+
*
|
66
|
+
* @returns {'table' | 'handsontable' | 'unrecognizable'}
|
67
|
+
*/
|
68
|
+
getType() {
|
69
|
+
if (this.isSerializedHandsontable()) {
|
70
|
+
return 'handsontable';
|
71
|
+
}
|
72
|
+
if (this.isSerializedTable()) {
|
73
|
+
return 'table';
|
74
|
+
}
|
75
|
+
return 'unrecognizable';
|
76
|
+
}
|
77
|
+
}
|
@@ -6,7 +6,6 @@ require("core-js/modules/es.error.cause.js");
|
|
6
6
|
var _base = require("../base");
|
7
7
|
var _pluginHooks = _interopRequireDefault(require("../../pluginHooks"));
|
8
8
|
var _SheetClip = require("../../3rdparty/SheetClip");
|
9
|
-
var _array = require("../../helpers/array");
|
10
9
|
var _string = require("../../helpers/string");
|
11
10
|
var _element = require("../../helpers/dom/element");
|
12
11
|
var _browser = require("../../helpers/browser");
|
@@ -15,10 +14,10 @@ var _copyColumnHeadersOnly = _interopRequireDefault(require("./contextMenuItem/c
|
|
15
14
|
var _copyWithColumnGroupHeaders = _interopRequireDefault(require("./contextMenuItem/copyWithColumnGroupHeaders"));
|
16
15
|
var _copyWithColumnHeaders = _interopRequireDefault(require("./contextMenuItem/copyWithColumnHeaders"));
|
17
16
|
var _cut = _interopRequireDefault(require("./contextMenuItem/cut"));
|
18
|
-
var _pasteEvent = _interopRequireDefault(require("./pasteEvent"));
|
19
17
|
var _copyableRanges = require("./copyableRanges");
|
20
18
|
var _parseTable = require("../../utils/parseTable");
|
21
19
|
var _eventManager = _interopRequireDefault(require("../../eventManager"));
|
20
|
+
var _clipboardData = require("./clipboardData");
|
22
21
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
23
22
|
function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
|
24
23
|
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
@@ -45,7 +44,6 @@ exports.PLUGIN_KEY = PLUGIN_KEY;
|
|
45
44
|
const PLUGIN_PRIORITY = 80;
|
46
45
|
exports.PLUGIN_PRIORITY = PLUGIN_PRIORITY;
|
47
46
|
const SETTING_KEYS = ['fragmentSelection'];
|
48
|
-
const META_HEAD = ['<meta name="generator" content="Handsontable"/>', '<style type="text/css">td{white-space:normal}br{mso-data-placement:same-cell}</style>'].join('');
|
49
47
|
|
50
48
|
/* eslint-disable jsdoc/require-description-complete-sentence */
|
51
49
|
/**
|
@@ -90,7 +88,6 @@ var _isTriggeredByCopy = /*#__PURE__*/new WeakMap();
|
|
90
88
|
var _isTriggeredByCut = /*#__PURE__*/new WeakMap();
|
91
89
|
var _copyableRangesFactory = /*#__PURE__*/new WeakMap();
|
92
90
|
var _ensureClipboardEventsGetTriggered = /*#__PURE__*/new WeakSet();
|
93
|
-
var _countCopiedHeaders = /*#__PURE__*/new WeakSet();
|
94
91
|
var _addContentEditableToHighlightedCell = /*#__PURE__*/new WeakSet();
|
95
92
|
var _removeContentEditableFromHighlightedCell = /*#__PURE__*/new WeakSet();
|
96
93
|
class CopyPaste extends _base.BasePlugin {
|
@@ -104,15 +101,6 @@ class CopyPaste extends _base.BasePlugin {
|
|
104
101
|
* Add the `contenteditable` attribute to the highlighted cell and select its content.
|
105
102
|
*/
|
106
103
|
_classPrivateMethodInitSpec(this, _addContentEditableToHighlightedCell);
|
107
|
-
/**
|
108
|
-
* Counts how many column headers will be copied based on the passed range.
|
109
|
-
*
|
110
|
-
* @private
|
111
|
-
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
|
112
|
-
* @returns {{ columnHeadersCount: number }} Returns an object with keys that holds
|
113
|
-
* information with the number of copied headers.
|
114
|
-
*/
|
115
|
-
_classPrivateMethodInitSpec(this, _countCopiedHeaders);
|
116
104
|
/**
|
117
105
|
* Ensure that the `copy`/`cut` events get triggered properly in Safari.
|
118
106
|
*
|
@@ -397,26 +385,14 @@ class CopyPaste extends _base.BasePlugin {
|
|
397
385
|
* @returns {Array[]} An array of arrays that will be copied to the clipboard.
|
398
386
|
*/
|
399
387
|
getRangedData(ranges) {
|
400
|
-
const data = [];
|
401
388
|
const {
|
402
389
|
rows,
|
403
390
|
columns
|
404
391
|
} = (0, _copyableRanges.normalizeRanges)(ranges);
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
const rowSet = [];
|
409
|
-
(0, _array.arrayEach)(columns, column => {
|
410
|
-
if (row < 0) {
|
411
|
-
// `row` as the second argument acts here as the `headerLevel` argument
|
412
|
-
rowSet.push(this.hot.getColHeader(column, row));
|
413
|
-
} else {
|
414
|
-
rowSet.push(this.hot.getCopyableData(row, column));
|
415
|
-
}
|
416
|
-
});
|
417
|
-
data.push(rowSet);
|
392
|
+
return (0, _parseTable.getDataByCoords)(this.hot, {
|
393
|
+
rows,
|
394
|
+
columns
|
418
395
|
});
|
419
|
-
return data;
|
420
396
|
}
|
421
397
|
|
422
398
|
/**
|
@@ -433,7 +409,17 @@ class CopyPaste extends _base.BasePlugin {
|
|
433
409
|
if (!pastableText && !pastableHtml) {
|
434
410
|
return;
|
435
411
|
}
|
436
|
-
const pasteData =
|
412
|
+
const pasteData = {
|
413
|
+
clipboardData: {
|
414
|
+
data: {},
|
415
|
+
setData(type, value) {
|
416
|
+
this.data[type] = value;
|
417
|
+
},
|
418
|
+
getData(type) {
|
419
|
+
return this.data[type];
|
420
|
+
}
|
421
|
+
}
|
422
|
+
};
|
437
423
|
if (pastableText) {
|
438
424
|
pasteData.clipboardData.setData('text/plain', pastableText);
|
439
425
|
}
|
@@ -572,7 +558,7 @@ class CopyPaste extends _base.BasePlugin {
|
|
572
558
|
/**
|
573
559
|
* `copy` event callback on textarea element.
|
574
560
|
*
|
575
|
-
* @param {
|
561
|
+
* @param {ClipboardEvent} event ClipboardEvent.
|
576
562
|
* @private
|
577
563
|
*/
|
578
564
|
onCopy(event) {
|
@@ -581,19 +567,12 @@ class CopyPaste extends _base.BasePlugin {
|
|
581
567
|
}
|
582
568
|
this.setCopyableText();
|
583
569
|
_classPrivateFieldSet(this, _isTriggeredByCopy, false);
|
584
|
-
const
|
585
|
-
const
|
586
|
-
const allowCopying = !!this.hot.runHooks('beforeCopy', data, this.copyableRanges, copiedHeadersCount);
|
570
|
+
const copyClipboardData = new _clipboardData.CopyClipboardData(this.hot, this.copyableRanges);
|
571
|
+
const allowCopying = !!this.hot.runHooks('beforeCopy', copyClipboardData);
|
587
572
|
if (allowCopying) {
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
event.clipboardData.setData('text/plain', textPlain);
|
592
|
-
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
593
|
-
} else if (typeof ClipboardEvent === 'undefined') {
|
594
|
-
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
595
|
-
}
|
596
|
-
this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
|
573
|
+
event.clipboardData.setData('text/plain', (0, _SheetClip.stringify)(copyClipboardData.getData()));
|
574
|
+
event.clipboardData.setData('text/html', [copyClipboardData.getType() === 'handsontable' ? _clipboardData.META_HEAD : '', (0, _parseTable.getHTMLFromConfig)(copyClipboardData.getMetaInfo())].join(''));
|
575
|
+
this.hot.runHooks('afterCopy', copyClipboardData);
|
597
576
|
}
|
598
577
|
_classPrivateFieldSet(this, _copyMode, 'cells-only');
|
599
578
|
event.preventDefault();
|
@@ -602,7 +581,7 @@ class CopyPaste extends _base.BasePlugin {
|
|
602
581
|
/**
|
603
582
|
* `cut` event callback on textarea element.
|
604
583
|
*
|
605
|
-
* @param {
|
584
|
+
* @param {ClipboardEvent} event ClipboardEvent.
|
606
585
|
* @private
|
607
586
|
*/
|
608
587
|
onCut(event) {
|
@@ -611,19 +590,13 @@ class CopyPaste extends _base.BasePlugin {
|
|
611
590
|
}
|
612
591
|
this.setCopyableText();
|
613
592
|
_classPrivateFieldSet(this, _isTriggeredByCut, false);
|
614
|
-
const
|
615
|
-
const allowCuttingOut = !!this.hot.runHooks('beforeCut',
|
593
|
+
const copyClipboardData = new _clipboardData.CopyClipboardData(this.hot, this.copyableRanges);
|
594
|
+
const allowCuttingOut = !!this.hot.runHooks('beforeCut', copyClipboardData);
|
616
595
|
if (allowCuttingOut) {
|
617
|
-
|
618
|
-
|
619
|
-
const textHTML = (0, _parseTable._dataToHTML)(rangedData, this.hot.rootDocument);
|
620
|
-
event.clipboardData.setData('text/plain', textPlain);
|
621
|
-
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
622
|
-
} else if (typeof ClipboardEvent === 'undefined') {
|
623
|
-
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
624
|
-
}
|
596
|
+
event.clipboardData.setData('text/plain', (0, _SheetClip.stringify)(copyClipboardData.getData()));
|
597
|
+
event.clipboardData.setData('text/html', [copyClipboardData.getType() === 'handsontable' ? _clipboardData.META_HEAD : '', (0, _parseTable.getHTMLFromConfig)(copyClipboardData.getMetaInfo())].join(''));
|
625
598
|
this.hot.emptySelectedCells('CopyPaste.cut');
|
626
|
-
this.hot.runHooks('afterCut',
|
599
|
+
this.hot.runHooks('afterCut', copyClipboardData);
|
627
600
|
}
|
628
601
|
event.preventDefault();
|
629
602
|
}
|
@@ -641,34 +614,22 @@ class CopyPaste extends _base.BasePlugin {
|
|
641
614
|
if (event && event.preventDefault) {
|
642
615
|
event.preventDefault();
|
643
616
|
}
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
if (textHTML && /(<table)|(<TABLE)/g.test(textHTML)) {
|
652
|
-
const parsedConfig = (0, _parseTable.htmlToGridSettings)(textHTML, this.hot.rootDocument);
|
653
|
-
pastedData = parsedConfig.data;
|
654
|
-
} else {
|
655
|
-
pastedData = event.clipboardData.getData('text/plain');
|
656
|
-
}
|
657
|
-
} else if (typeof ClipboardEvent === 'undefined' && typeof this.hot.rootWindow.clipboardData !== 'undefined') {
|
658
|
-
pastedData = this.hot.rootWindow.clipboardData.getData('Text');
|
659
|
-
}
|
660
|
-
if (typeof pastedData === 'string') {
|
661
|
-
pastedData = (0, _SheetClip.parse)(pastedData);
|
662
|
-
}
|
663
|
-
if (pastedData === void 0 || pastedData && pastedData.length === 0) {
|
617
|
+
const html = (0, _string.sanitize)(event.clipboardData.getData('text/html'), {
|
618
|
+
ADD_TAGS: ['meta'],
|
619
|
+
ADD_ATTR: ['content'],
|
620
|
+
FORCE_BODY: true
|
621
|
+
});
|
622
|
+
const pasteClipboardData = new _clipboardData.PasteClipboardData(event.clipboardData.getData('text/plain'), html);
|
623
|
+
if (this.hot.runHooks('beforePaste', pasteClipboardData) === false) {
|
664
624
|
return;
|
665
625
|
}
|
666
|
-
|
626
|
+
const pastedTable = pasteClipboardData.getData();
|
627
|
+
if (pastedTable.length === 0) {
|
667
628
|
return;
|
668
629
|
}
|
669
|
-
const [startRow, startColumn, endRow, endColumn] = this.populateValues(
|
630
|
+
const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedTable);
|
670
631
|
this.hot.selectCell(startRow, startColumn, Math.min(this.hot.countRows() - 1, endRow), Math.min(this.hot.countCols() - 1, endColumn));
|
671
|
-
this.hot.runHooks('afterPaste',
|
632
|
+
this.hot.runHooks('afterPaste', pasteClipboardData);
|
672
633
|
}
|
673
634
|
|
674
635
|
/**
|
@@ -765,21 +726,6 @@ function _ensureClipboardEventsGetTriggered2(eventName) {
|
|
765
726
|
this.hot.rootDocument.execCommand(eventName);
|
766
727
|
}
|
767
728
|
}
|
768
|
-
function _countCopiedHeaders2(ranges) {
|
769
|
-
const {
|
770
|
-
rows
|
771
|
-
} = (0, _copyableRanges.normalizeRanges)(ranges);
|
772
|
-
let columnHeadersCount = 0;
|
773
|
-
for (let row = 0; row < rows.length; row++) {
|
774
|
-
if (rows[row] >= 0) {
|
775
|
-
break;
|
776
|
-
}
|
777
|
-
columnHeadersCount += 1;
|
778
|
-
}
|
779
|
-
return {
|
780
|
-
columnHeadersCount
|
781
|
-
};
|
782
|
-
}
|
783
729
|
function _addContentEditableToHighlightedCell2() {
|
784
730
|
if (this.hot.isListening()) {
|
785
731
|
const lastSelectedRange = this.hot.getSelectedRangeLast();
|
@@ -14,8 +14,7 @@ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!priva
|
|
14
14
|
function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
|
15
15
|
import { BasePlugin } from "../base/index.mjs";
|
16
16
|
import Hooks from "../../pluginHooks.mjs";
|
17
|
-
import { stringify
|
18
|
-
import { arrayEach } from "../../helpers/array.mjs";
|
17
|
+
import { stringify } from "../../3rdparty/SheetClip/index.mjs";
|
19
18
|
import { sanitize } from "../../helpers/string.mjs";
|
20
19
|
import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent } from "../../helpers/dom/element.mjs";
|
21
20
|
import { isSafari } from "../../helpers/browser.mjs";
|
@@ -24,10 +23,10 @@ import copyColumnHeadersOnlyItem from "./contextMenuItem/copyColumnHeadersOnly.m
|
|
24
23
|
import copyWithColumnGroupHeadersItem from "./contextMenuItem/copyWithColumnGroupHeaders.mjs";
|
25
24
|
import copyWithColumnHeadersItem from "./contextMenuItem/copyWithColumnHeaders.mjs";
|
26
25
|
import cutItem from "./contextMenuItem/cut.mjs";
|
27
|
-
import PasteEvent from "./pasteEvent.mjs";
|
28
26
|
import { CopyableRangesFactory, normalizeRanges } from "./copyableRanges.mjs";
|
29
|
-
import {
|
27
|
+
import { getDataByCoords, getHTMLFromConfig } from "../../utils/parseTable.mjs";
|
30
28
|
import EventManager from "../../eventManager.mjs";
|
29
|
+
import { CopyClipboardData, PasteClipboardData, META_HEAD } from "./clipboardData/index.mjs";
|
31
30
|
Hooks.getSingleton().register('afterCopyLimit');
|
32
31
|
Hooks.getSingleton().register('modifyCopyableRange');
|
33
32
|
Hooks.getSingleton().register('beforeCut');
|
@@ -39,7 +38,6 @@ Hooks.getSingleton().register('afterCopy');
|
|
39
38
|
export const PLUGIN_KEY = 'copyPaste';
|
40
39
|
export const PLUGIN_PRIORITY = 80;
|
41
40
|
const SETTING_KEYS = ['fragmentSelection'];
|
42
|
-
const META_HEAD = ['<meta name="generator" content="Handsontable"/>', '<style type="text/css">td{white-space:normal}br{mso-data-placement:same-cell}</style>'].join('');
|
43
41
|
|
44
42
|
/* eslint-disable jsdoc/require-description-complete-sentence */
|
45
43
|
/**
|
@@ -84,7 +82,6 @@ var _isTriggeredByCopy = /*#__PURE__*/new WeakMap();
|
|
84
82
|
var _isTriggeredByCut = /*#__PURE__*/new WeakMap();
|
85
83
|
var _copyableRangesFactory = /*#__PURE__*/new WeakMap();
|
86
84
|
var _ensureClipboardEventsGetTriggered = /*#__PURE__*/new WeakSet();
|
87
|
-
var _countCopiedHeaders = /*#__PURE__*/new WeakSet();
|
88
85
|
var _addContentEditableToHighlightedCell = /*#__PURE__*/new WeakSet();
|
89
86
|
var _removeContentEditableFromHighlightedCell = /*#__PURE__*/new WeakSet();
|
90
87
|
export class CopyPaste extends BasePlugin {
|
@@ -98,15 +95,6 @@ export class CopyPaste extends BasePlugin {
|
|
98
95
|
* Add the `contenteditable` attribute to the highlighted cell and select its content.
|
99
96
|
*/
|
100
97
|
_classPrivateMethodInitSpec(this, _addContentEditableToHighlightedCell);
|
101
|
-
/**
|
102
|
-
* Counts how many column headers will be copied based on the passed range.
|
103
|
-
*
|
104
|
-
* @private
|
105
|
-
* @param {Array<{startRow: number, startCol: number, endRow: number, endCol: number}>} ranges Array of objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
|
106
|
-
* @returns {{ columnHeadersCount: number }} Returns an object with keys that holds
|
107
|
-
* information with the number of copied headers.
|
108
|
-
*/
|
109
|
-
_classPrivateMethodInitSpec(this, _countCopiedHeaders);
|
110
98
|
/**
|
111
99
|
* Ensure that the `copy`/`cut` events get triggered properly in Safari.
|
112
100
|
*
|
@@ -391,26 +379,14 @@ export class CopyPaste extends BasePlugin {
|
|
391
379
|
* @returns {Array[]} An array of arrays that will be copied to the clipboard.
|
392
380
|
*/
|
393
381
|
getRangedData(ranges) {
|
394
|
-
const data = [];
|
395
382
|
const {
|
396
383
|
rows,
|
397
384
|
columns
|
398
385
|
} = normalizeRanges(ranges);
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
const rowSet = [];
|
403
|
-
arrayEach(columns, column => {
|
404
|
-
if (row < 0) {
|
405
|
-
// `row` as the second argument acts here as the `headerLevel` argument
|
406
|
-
rowSet.push(this.hot.getColHeader(column, row));
|
407
|
-
} else {
|
408
|
-
rowSet.push(this.hot.getCopyableData(row, column));
|
409
|
-
}
|
410
|
-
});
|
411
|
-
data.push(rowSet);
|
386
|
+
return getDataByCoords(this.hot, {
|
387
|
+
rows,
|
388
|
+
columns
|
412
389
|
});
|
413
|
-
return data;
|
414
390
|
}
|
415
391
|
|
416
392
|
/**
|
@@ -427,7 +403,17 @@ export class CopyPaste extends BasePlugin {
|
|
427
403
|
if (!pastableText && !pastableHtml) {
|
428
404
|
return;
|
429
405
|
}
|
430
|
-
const pasteData =
|
406
|
+
const pasteData = {
|
407
|
+
clipboardData: {
|
408
|
+
data: {},
|
409
|
+
setData(type, value) {
|
410
|
+
this.data[type] = value;
|
411
|
+
},
|
412
|
+
getData(type) {
|
413
|
+
return this.data[type];
|
414
|
+
}
|
415
|
+
}
|
416
|
+
};
|
431
417
|
if (pastableText) {
|
432
418
|
pasteData.clipboardData.setData('text/plain', pastableText);
|
433
419
|
}
|
@@ -566,7 +552,7 @@ export class CopyPaste extends BasePlugin {
|
|
566
552
|
/**
|
567
553
|
* `copy` event callback on textarea element.
|
568
554
|
*
|
569
|
-
* @param {
|
555
|
+
* @param {ClipboardEvent} event ClipboardEvent.
|
570
556
|
* @private
|
571
557
|
*/
|
572
558
|
onCopy(event) {
|
@@ -575,19 +561,12 @@ export class CopyPaste extends BasePlugin {
|
|
575
561
|
}
|
576
562
|
this.setCopyableText();
|
577
563
|
_classPrivateFieldSet(this, _isTriggeredByCopy, false);
|
578
|
-
const
|
579
|
-
const
|
580
|
-
const allowCopying = !!this.hot.runHooks('beforeCopy', data, this.copyableRanges, copiedHeadersCount);
|
564
|
+
const copyClipboardData = new CopyClipboardData(this.hot, this.copyableRanges);
|
565
|
+
const allowCopying = !!this.hot.runHooks('beforeCopy', copyClipboardData);
|
581
566
|
if (allowCopying) {
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
event.clipboardData.setData('text/plain', textPlain);
|
586
|
-
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
587
|
-
} else if (typeof ClipboardEvent === 'undefined') {
|
588
|
-
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
589
|
-
}
|
590
|
-
this.hot.runHooks('afterCopy', data, this.copyableRanges, copiedHeadersCount);
|
567
|
+
event.clipboardData.setData('text/plain', stringify(copyClipboardData.getData()));
|
568
|
+
event.clipboardData.setData('text/html', [copyClipboardData.getType() === 'handsontable' ? META_HEAD : '', getHTMLFromConfig(copyClipboardData.getMetaInfo())].join(''));
|
569
|
+
this.hot.runHooks('afterCopy', copyClipboardData);
|
591
570
|
}
|
592
571
|
_classPrivateFieldSet(this, _copyMode, 'cells-only');
|
593
572
|
event.preventDefault();
|
@@ -596,7 +575,7 @@ export class CopyPaste extends BasePlugin {
|
|
596
575
|
/**
|
597
576
|
* `cut` event callback on textarea element.
|
598
577
|
*
|
599
|
-
* @param {
|
578
|
+
* @param {ClipboardEvent} event ClipboardEvent.
|
600
579
|
* @private
|
601
580
|
*/
|
602
581
|
onCut(event) {
|
@@ -605,19 +584,13 @@ export class CopyPaste extends BasePlugin {
|
|
605
584
|
}
|
606
585
|
this.setCopyableText();
|
607
586
|
_classPrivateFieldSet(this, _isTriggeredByCut, false);
|
608
|
-
const
|
609
|
-
const allowCuttingOut = !!this.hot.runHooks('beforeCut',
|
587
|
+
const copyClipboardData = new CopyClipboardData(this.hot, this.copyableRanges);
|
588
|
+
const allowCuttingOut = !!this.hot.runHooks('beforeCut', copyClipboardData);
|
610
589
|
if (allowCuttingOut) {
|
611
|
-
|
612
|
-
|
613
|
-
const textHTML = _dataToHTML(rangedData, this.hot.rootDocument);
|
614
|
-
event.clipboardData.setData('text/plain', textPlain);
|
615
|
-
event.clipboardData.setData('text/html', [META_HEAD, textHTML].join(''));
|
616
|
-
} else if (typeof ClipboardEvent === 'undefined') {
|
617
|
-
this.hot.rootWindow.clipboardData.setData('Text', textPlain);
|
618
|
-
}
|
590
|
+
event.clipboardData.setData('text/plain', stringify(copyClipboardData.getData()));
|
591
|
+
event.clipboardData.setData('text/html', [copyClipboardData.getType() === 'handsontable' ? META_HEAD : '', getHTMLFromConfig(copyClipboardData.getMetaInfo())].join(''));
|
619
592
|
this.hot.emptySelectedCells('CopyPaste.cut');
|
620
|
-
this.hot.runHooks('afterCut',
|
593
|
+
this.hot.runHooks('afterCut', copyClipboardData);
|
621
594
|
}
|
622
595
|
event.preventDefault();
|
623
596
|
}
|
@@ -635,34 +608,22 @@ export class CopyPaste extends BasePlugin {
|
|
635
608
|
if (event && event.preventDefault) {
|
636
609
|
event.preventDefault();
|
637
610
|
}
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
if (textHTML && /(<table)|(<TABLE)/g.test(textHTML)) {
|
646
|
-
const parsedConfig = htmlToGridSettings(textHTML, this.hot.rootDocument);
|
647
|
-
pastedData = parsedConfig.data;
|
648
|
-
} else {
|
649
|
-
pastedData = event.clipboardData.getData('text/plain');
|
650
|
-
}
|
651
|
-
} else if (typeof ClipboardEvent === 'undefined' && typeof this.hot.rootWindow.clipboardData !== 'undefined') {
|
652
|
-
pastedData = this.hot.rootWindow.clipboardData.getData('Text');
|
653
|
-
}
|
654
|
-
if (typeof pastedData === 'string') {
|
655
|
-
pastedData = parse(pastedData);
|
656
|
-
}
|
657
|
-
if (pastedData === void 0 || pastedData && pastedData.length === 0) {
|
611
|
+
const html = sanitize(event.clipboardData.getData('text/html'), {
|
612
|
+
ADD_TAGS: ['meta'],
|
613
|
+
ADD_ATTR: ['content'],
|
614
|
+
FORCE_BODY: true
|
615
|
+
});
|
616
|
+
const pasteClipboardData = new PasteClipboardData(event.clipboardData.getData('text/plain'), html);
|
617
|
+
if (this.hot.runHooks('beforePaste', pasteClipboardData) === false) {
|
658
618
|
return;
|
659
619
|
}
|
660
|
-
|
620
|
+
const pastedTable = pasteClipboardData.getData();
|
621
|
+
if (pastedTable.length === 0) {
|
661
622
|
return;
|
662
623
|
}
|
663
|
-
const [startRow, startColumn, endRow, endColumn] = this.populateValues(
|
624
|
+
const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedTable);
|
664
625
|
this.hot.selectCell(startRow, startColumn, Math.min(this.hot.countRows() - 1, endRow), Math.min(this.hot.countCols() - 1, endColumn));
|
665
|
-
this.hot.runHooks('afterPaste',
|
626
|
+
this.hot.runHooks('afterPaste', pasteClipboardData);
|
666
627
|
}
|
667
628
|
|
668
629
|
/**
|
@@ -758,21 +719,6 @@ function _ensureClipboardEventsGetTriggered2(eventName) {
|
|
758
719
|
this.hot.rootDocument.execCommand(eventName);
|
759
720
|
}
|
760
721
|
}
|
761
|
-
function _countCopiedHeaders2(ranges) {
|
762
|
-
const {
|
763
|
-
rows
|
764
|
-
} = normalizeRanges(ranges);
|
765
|
-
let columnHeadersCount = 0;
|
766
|
-
for (let row = 0; row < rows.length; row++) {
|
767
|
-
if (rows[row] >= 0) {
|
768
|
-
break;
|
769
|
-
}
|
770
|
-
columnHeadersCount += 1;
|
771
|
-
}
|
772
|
-
return {
|
773
|
-
columnHeadersCount
|
774
|
-
};
|
775
|
-
}
|
776
722
|
function _addContentEditableToHighlightedCell2() {
|
777
723
|
if (this.hot.isListening()) {
|
778
724
|
const lastSelectedRange = this.hot.getSelectedRangeLast();
|