diff --git a/package-lock.json b/package-lock.json index 13a30cde7b1..02d2d61c29f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4825,8 +4825,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -4847,14 +4846,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4869,20 +4866,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4999,8 +4993,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5012,7 +5005,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5027,7 +5019,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5035,14 +5026,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5061,7 +5050,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5142,8 +5130,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5155,7 +5142,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5241,8 +5227,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -5278,7 +5263,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5298,7 +5282,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5342,14 +5325,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/src/core.js b/src/core.js index 70eb9da6f57..ecd6a007ea4 100644 --- a/src/core.js +++ b/src/core.js @@ -18,6 +18,7 @@ import { objectEach } from './helpers/object'; import { arrayFlatten, arrayMap, arrayEach, arrayReduce } from './helpers/array'; +import { instanceToHTML } from './utils/parseTable'; import { getPlugin } from './plugins'; import { getRenderer } from './renderers'; import { getValidator } from './validators'; @@ -3555,6 +3556,26 @@ export default function Core(rootElement, userSettings, rootInstanceSymbol = fal return getTranslatedPhrase(priv.settings.language, dictionaryKey, extraArguments); }; + /** + * Converts instance into outerHTML of HTMLTableElement. + * + * @memberof Core# + * @function toString + * @since 7.1.0 + * @returns {HTMLTableElement} + */ + this.toString = () => instanceToHTML(this); + + /** + * Converts instance into outerHTML of HTMLTableElement. + * + * @memberof Core# + * @function toHTML + * @since 7.1.0 + * @returns {HTMLTableElement} + */ + this.toHTML = () => instanceToHTML(this); + this.timeouts = []; /** diff --git a/src/index.js b/src/index.js index ec69c74c026..dda16875742 100644 --- a/src/index.js +++ b/src/index.js @@ -173,4 +173,20 @@ Handsontable.languages.registerLanguageDictionary = registerLanguageDictionary; // Alias to `getTranslatedPhrase` function, for more information check it API. Handsontable.languages.getTranslatedPhrase = (...args) => getTranslatedPhrase(...args); +/** + * Prepares Handsontable configuration based on HTMLElement. + * + * @param {Node} element Node element to prepare Handsontable configuration. + * @returns {DefaultSettings} Object with Handsontable configuration. + */ +Handsontable.fromHTML = element => Handsontable.helper.tableToSettings(element); + +/** + * Prepares Handsontable configuration based on string. + * + * @param {String} htmlText Node element to prepare Handsontable configuration. + * @returns {DefaultSettings} Object with Handsontable configuration. + */ +Handsontable.fromString = htmlText => Handsontable.helper.tableToSettings(htmlText); + export default Handsontable; diff --git a/src/plugins/copyPaste/copyPaste.js b/src/plugins/copyPaste/copyPaste.js index 25d810a4241..5ae66b42bda 100644 --- a/src/plugins/copyPaste/copyPaste.js +++ b/src/plugins/copyPaste/copyPaste.js @@ -9,7 +9,7 @@ import copyItem from './contextMenuItem/copy'; import cutItem from './contextMenuItem/cut'; import PasteEvent from './pasteEvent'; import { createElement, destroyElement } from './focusableElement'; -import { arrayToTable, tableToHandsontable } from './../../utils/parseTable'; +import { arrayToHTML, tableToSettings } from './../../utils/parseTable'; import './copyPaste.css'; @@ -411,7 +411,7 @@ class CopyPaste extends BasePlugin { const textPlain = SheetClip.stringify(rangedData); if (event && event.clipboardData) { - const textHTML = arrayToTable(rangedData, this.hot.rootDocument); + const textHTML = arrayToHTML(rangedData, this.hot.rootDocument); event.clipboardData.setData('text/plain', textPlain); event.clipboardData.setData('text/html', textHTML); @@ -449,7 +449,7 @@ class CopyPaste extends BasePlugin { const textPlain = SheetClip.stringify(rangedData); if (event && event.clipboardData) { - const textHTML = arrayToTable(rangedData, this.hot.rootDocument); + const textHTML = arrayToHTML(rangedData, this.hot.rootDocument); event.clipboardData.setData('text/plain', textPlain); event.clipboardData.setData('text/html', textHTML); @@ -481,13 +481,13 @@ class CopyPaste extends BasePlugin { } let pastedData; - let parsedConfig; + let parsedConfig = {}; if (event && typeof event.clipboardData !== 'undefined') { const textHTML = event.clipboardData.getData('text/html'); if (textHTML && /( { await sleep(60); expect(beforePasteSpy.calls.count()).toEqual(1); - expect(beforePasteSpy).toHaveBeenCalledWith([['Kia']], [{ startRow: 0, startCol: 0, endRow: 0, endCol: 0 }], void 0, void 0, void 0, void 0); + expect(beforePasteSpy).toHaveBeenCalledWith([['Kia']], [{ startRow: 0, startCol: 0, endRow: 0, endCol: 0 }], {}, void 0, void 0, void 0); expect(afterPasteSpy.calls.count()).toEqual(1); - expect(afterPasteSpy).toHaveBeenCalledWith([['Kia']], [{ startRow: 0, startCol: 0, endRow: 0, endCol: 0 }], void 0, void 0, void 0, void 0); + expect(afterPasteSpy).toHaveBeenCalledWith([['Kia']], [{ startRow: 0, startCol: 0, endRow: 0, endCol: 0 }], {}, void 0, void 0, void 0); }); it('should be possible to block pasting', async() => { diff --git a/src/utils/parseTable.js b/src/utils/parseTable.js index 4c6e1f1b4a5..ad15067fd87 100644 --- a/src/utils/parseTable.js +++ b/src/utils/parseTable.js @@ -1,10 +1,22 @@ import { isEmpty } from './../helpers/mixed'; /** - * Converts Handsontable into HTMLTableElement - * @param {Handsontable} instance + * Verifies if node is an HTMLTable element. + * + * @param {Node} element Node to verify if it's an HTMLTable. */ -export function convertToHTMLTable({ instance }) { +function isHTMLTable(element) { + return (element && element.nodeName || '').toLowerCase() === 'table'; +} + +/** + * Converts Handsontable into HTMLTableElement. + * + * @param {Core} instance + * + * @returns {String} outerHTML of the HTMLTableElement + */ +export function instanceToHTML(instance) { const doc = instance.rootDocument; const hasColumnHeaders = instance.hasColHeaders(); const hasRowHeaders = instance.hasRowHeaders(); @@ -72,11 +84,15 @@ export function convertToHTMLTable({ instance }) { } /** - * Converts javascript array into HTMLTable. + * Converts 2D array into HTMLTableElement. * * @param {Array} input Input array which will be converted to HTMLTable + * @param {Document} [rootDocument] + * + * @returns {String} outerHTML of the HTMLTableElement */ -export function arrayToTable(input, rootDocument) { +// eslint-disable-next-line no-restricted-globals +export function arrayToHTML(input, rootDocument = document) { const inputLen = input.length; const result = ['', '']; @@ -99,12 +115,7 @@ export function arrayToTable(input, rootDocument) { '' : cellData.toString().replace(/((\r\n|\n)?|\r\n|\n)/g, '
\r\n').replace(/\x20/gi, ' ').replace(/\t/gi, ' '); - // tempElement.innerText = `${isEmpty(rowData[column]) ? '' : rowData[column]}`; - columnsResult.push(`
`); - - // columnsResult.push(``); - // columnsResult.push(``); } result.push('', ...columnsResult, ''); @@ -114,29 +125,19 @@ export function arrayToTable(input, rootDocument) { } } - // rootDocument.documentElement.removeChild(tempElement); - result.push('
${parsedCellData}${tempElement.innerHTML.replace(/
/g, '\r\n')}
${tempElement.innerHTML.replace(/
/g, '
\r\n')}
'); return result.join(''); } -/** - * Helper to verify if DOM element is an HTMLTable element. - * - * @param {Element} element Node element to verify if it's an HTMLTable. - */ -function isHTMLTable(element) { - return (element && element.nodeName || '').toLowerCase() === 'table'; -} - /** * Converts HTMLTable or string into Handsontable configuration object. * * @param {Element|String} element Node element or string, which should contain `...
`. + * @param {Document} [rootDocument] */ // eslint-disable-next-line no-restricted-globals -export function tableToHandsontable(element, rootDocument = document) { +export function tableToSettings(element, rootDocument = document) { const settingsObj = {}; const fragment = rootDocument.createDocumentFragment(); const tempElem = rootDocument.createElement('div');