handsontable 0.0.0-next-50e428d-20231026 → 0.0.0-next-42d5bd7-20231027

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.

Files changed (84) hide show
  1. package/3rdparty/walkontable/src/renderer/columnHeaders.js +3 -0
  2. package/3rdparty/walkontable/src/renderer/columnHeaders.mjs +4 -1
  3. package/3rdparty/walkontable/src/renderer/rowHeaders.js +3 -0
  4. package/3rdparty/walkontable/src/renderer/rowHeaders.mjs +4 -1
  5. package/base.js +2 -2
  6. package/base.mjs +2 -2
  7. package/core.js +1 -1
  8. package/core.mjs +1 -1
  9. package/dist/handsontable.css +45 -63
  10. package/dist/handsontable.full.css +45 -63
  11. package/dist/handsontable.full.js +3599 -2080
  12. package/dist/handsontable.full.min.css +5 -5
  13. package/dist/handsontable.full.min.js +70 -63
  14. package/dist/handsontable.js +3601 -2082
  15. package/dist/handsontable.min.css +5 -5
  16. package/dist/handsontable.min.js +25 -18
  17. package/dist/languages/all.js +24 -2
  18. package/dist/languages/all.min.js +1 -1
  19. package/dist/languages/en-US.js +12 -1
  20. package/dist/languages/en-US.min.js +1 -1
  21. package/dist/languages/pl-PL.js +12 -1
  22. package/dist/languages/pl-PL.min.js +1 -1
  23. package/helpers/a11y.js +2 -0
  24. package/helpers/a11y.mjs +1 -0
  25. package/helpers/dom/element.js +29 -0
  26. package/helpers/dom/element.mjs +28 -0
  27. package/helpers/mixed.js +1 -1
  28. package/helpers/mixed.mjs +1 -1
  29. package/i18n/constants.js +27 -1
  30. package/i18n/constants.mjs +14 -1
  31. package/i18n/languages/en-US.js +12 -1
  32. package/i18n/languages/en-US.mjs +12 -1
  33. package/i18n/languages/pl-PL.js +12 -1
  34. package/i18n/languages/pl-PL.mjs +12 -1
  35. package/languages/all.js +24 -2
  36. package/languages/en-US.js +12 -1
  37. package/languages/en-US.mjs +12 -1
  38. package/languages/index.js +24 -2
  39. package/languages/pl-PL.js +12 -1
  40. package/languages/pl-PL.mjs +12 -1
  41. package/package.json +1 -1
  42. package/pluginHooks.d.ts +28 -6
  43. package/pluginHooks.js +116 -62
  44. package/pluginHooks.mjs +116 -62
  45. package/plugins/collapsibleColumns/collapsibleColumns.js +3 -2
  46. package/plugins/collapsibleColumns/collapsibleColumns.mjs +4 -3
  47. package/plugins/columnSorting/columnSorting.js +29 -3
  48. package/plugins/columnSorting/columnSorting.mjs +31 -5
  49. package/plugins/contextMenu/menu/menuItemRenderer.js +12 -0
  50. package/plugins/contextMenu/menu/menuItemRenderer.mjs +14 -2
  51. package/plugins/copyPaste/clipboardData/clipboardData.js +517 -0
  52. package/plugins/copyPaste/clipboardData/clipboardData.mjs +512 -0
  53. package/plugins/copyPaste/clipboardData/copyClipboardData.js +69 -0
  54. package/plugins/copyPaste/clipboardData/copyClipboardData.mjs +65 -0
  55. package/plugins/copyPaste/clipboardData/index.js +9 -0
  56. package/plugins/copyPaste/clipboardData/index.mjs +4 -0
  57. package/plugins/copyPaste/clipboardData/pasteClipboardData.js +81 -0
  58. package/plugins/copyPaste/clipboardData/pasteClipboardData.mjs +77 -0
  59. package/plugins/copyPaste/copyPaste.js +38 -92
  60. package/plugins/copyPaste/copyPaste.mjs +40 -94
  61. package/plugins/dropdownMenu/dropdownMenu.js +2 -1
  62. package/plugins/dropdownMenu/dropdownMenu.mjs +3 -2
  63. package/plugins/filters/ui/input.js +0 -3
  64. package/plugins/filters/ui/input.mjs +0 -3
  65. package/plugins/filters/ui/select.js +6 -0
  66. package/plugins/filters/ui/select.mjs +6 -0
  67. package/plugins/hiddenColumns/hiddenColumns.js +48 -3
  68. package/plugins/hiddenColumns/hiddenColumns.mjs +47 -2
  69. package/plugins/hiddenRows/hiddenRows.js +48 -3
  70. package/plugins/hiddenRows/hiddenRows.mjs +47 -2
  71. package/plugins/multiColumnSorting/multiColumnSorting.js +21 -0
  72. package/plugins/multiColumnSorting/multiColumnSorting.mjs +22 -1
  73. package/plugins/nestedHeaders/nestedHeaders.js +21 -22
  74. package/plugins/nestedHeaders/nestedHeaders.mjs +21 -22
  75. package/plugins/nestedRows/nestedRows.js +2 -1
  76. package/plugins/nestedRows/nestedRows.mjs +2 -1
  77. package/plugins/nestedRows/ui/headers.js +3 -3
  78. package/plugins/nestedRows/ui/headers.mjs +4 -4
  79. package/utils/parseTable.js +527 -83
  80. package/utils/parseTable.mjs +523 -82
  81. package/plugins/copyPaste/clipboardData.js +0 -18
  82. package/plugins/copyPaste/clipboardData.mjs +0 -14
  83. package/plugins/copyPaste/pasteEvent.js +0 -14
  84. 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
- // concatenate all rows and columns data defined in ranges into one copyable string
407
- (0, _array.arrayEach)(rows, row => {
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 = new _pasteEvent.default();
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 {Event} event ClipboardEvent.
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 data = this.getRangedData(this.copyableRanges);
585
- const copiedHeadersCount = _classPrivateMethodGet(this, _countCopiedHeaders, _countCopiedHeaders2).call(this, this.copyableRanges);
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
- const textPlain = (0, _SheetClip.stringify)(data);
589
- if (event && event.clipboardData) {
590
- const textHTML = (0, _parseTable._dataToHTML)(data, this.hot.rootDocument);
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 {Event} event ClipboardEvent.
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 rangedData = this.getRangedData(this.copyableRanges);
615
- const allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);
593
+ const copyClipboardData = new _clipboardData.CopyClipboardData(this.hot, this.copyableRanges);
594
+ const allowCuttingOut = !!this.hot.runHooks('beforeCut', copyClipboardData);
616
595
  if (allowCuttingOut) {
617
- const textPlain = (0, _SheetClip.stringify)(rangedData);
618
- if (event && event.clipboardData) {
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', rangedData, this.copyableRanges);
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
- let pastedData;
645
- if (event && typeof event.clipboardData !== 'undefined') {
646
- const textHTML = (0, _string.sanitize)(event.clipboardData.getData('text/html'), {
647
- ADD_TAGS: ['meta'],
648
- ADD_ATTR: ['content'],
649
- FORCE_BODY: true
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
- if (this.hot.runHooks('beforePaste', pastedData, this.copyableRanges) === false) {
626
+ const pastedTable = pasteClipboardData.getData();
627
+ if (pastedTable.length === 0) {
667
628
  return;
668
629
  }
669
- const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedData);
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', pastedData, this.copyableRanges);
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, parse } from "../../3rdparty/SheetClip/index.mjs";
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 { _dataToHTML, htmlToGridSettings } from "../../utils/parseTable.mjs";
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
- // concatenate all rows and columns data defined in ranges into one copyable string
401
- arrayEach(rows, row => {
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 = new PasteEvent();
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 {Event} event ClipboardEvent.
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 data = this.getRangedData(this.copyableRanges);
579
- const copiedHeadersCount = _classPrivateMethodGet(this, _countCopiedHeaders, _countCopiedHeaders2).call(this, this.copyableRanges);
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
- const textPlain = stringify(data);
583
- if (event && event.clipboardData) {
584
- const textHTML = _dataToHTML(data, this.hot.rootDocument);
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 {Event} event ClipboardEvent.
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 rangedData = this.getRangedData(this.copyableRanges);
609
- const allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);
587
+ const copyClipboardData = new CopyClipboardData(this.hot, this.copyableRanges);
588
+ const allowCuttingOut = !!this.hot.runHooks('beforeCut', copyClipboardData);
610
589
  if (allowCuttingOut) {
611
- const textPlain = stringify(rangedData);
612
- if (event && event.clipboardData) {
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', rangedData, this.copyableRanges);
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
- let pastedData;
639
- if (event && typeof event.clipboardData !== 'undefined') {
640
- const textHTML = sanitize(event.clipboardData.getData('text/html'), {
641
- ADD_TAGS: ['meta'],
642
- ADD_ATTR: ['content'],
643
- FORCE_BODY: true
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
- if (this.hot.runHooks('beforePaste', pastedData, this.copyableRanges) === false) {
620
+ const pastedTable = pasteClipboardData.getData();
621
+ if (pastedTable.length === 0) {
661
622
  return;
662
623
  }
663
- const [startRow, startColumn, endRow, endColumn] = this.populateValues(pastedData);
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', pastedData, this.copyableRanges);
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();
@@ -13,6 +13,7 @@ var _itemsFactory = require("../contextMenu/itemsFactory");
13
13
  var _menu = require("../contextMenu/menu");
14
14
  var _pluginHooks = _interopRequireDefault(require("../../pluginHooks"));
15
15
  var _predefinedItems = require("../contextMenu/predefinedItems");
16
+ var _constants = require("../../i18n/constants");
16
17
  var _a11y = require("../../helpers/a11y");
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
19
  function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
@@ -439,7 +440,7 @@ class DropdownMenu extends _base.BasePlugin {
439
440
  button.type = 'button';
440
441
  button.tabIndex = -1;
441
442
  if (this.hot.getSettings().ariaTags) {
442
- (0, _element.setAttribute)(button, [(0, _a11y.A11Y_HIDDEN)()]);
443
+ (0, _element.setAttribute)(button, [(0, _a11y.A11Y_LABEL)(this.hot.getTranslatedPhrase(_constants.COLUMN_HEADER_LABEL_OPEN_MENU))]);
443
444
  (0, _element.setAttribute)(TH, [(0, _a11y.A11Y_HASPOPUP)('menu')]);
444
445
  }
445
446
 
@@ -13,7 +13,8 @@ import { ItemsFactory } from "../contextMenu/itemsFactory.mjs";
13
13
  import { Menu } from "../contextMenu/menu/index.mjs";
14
14
  import Hooks from "../../pluginHooks.mjs";
15
15
  import { COLUMN_LEFT, COLUMN_RIGHT, REMOVE_COLUMN, CLEAR_COLUMN, READ_ONLY, ALIGNMENT, SEPARATOR } from "../contextMenu/predefinedItems/index.mjs";
16
- import { A11Y_HASPOPUP, A11Y_HIDDEN } from "../../helpers/a11y.mjs";
16
+ import { COLUMN_HEADER_LABEL_OPEN_MENU } from "../../i18n/constants.mjs";
17
+ import { A11Y_LABEL, A11Y_HASPOPUP } from "../../helpers/a11y.mjs";
17
18
  Hooks.getSingleton().register('afterDropdownMenuDefaultOptions');
18
19
  Hooks.getSingleton().register('beforeDropdownMenuShow');
19
20
  Hooks.getSingleton().register('afterDropdownMenuShow');
@@ -433,7 +434,7 @@ export class DropdownMenu extends BasePlugin {
433
434
  button.type = 'button';
434
435
  button.tabIndex = -1;
435
436
  if (this.hot.getSettings().ariaTags) {
436
- setAttribute(button, [A11Y_HIDDEN()]);
437
+ setAttribute(button, [A11Y_LABEL(this.hot.getTranslatedPhrase(COLUMN_HEADER_LABEL_OPEN_MENU))]);
437
438
  setAttribute(TH, [A11Y_HASPOPUP('menu')]);
438
439
  }
439
440