From f94ca834b1fdee94e4e44bdc3d245956a4437de6 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Mon, 8 Nov 2021 20:06:12 -0500 Subject: [PATCH] fix(context): strip hidden special chars on context menu Copy command - there were some hidden characters that were carried over when doing copy+paste, and the only way I found to fix that was to replace `\u034f` (unicode char) with empty string - we should also trim the string to remove any empty spaces from start/end of string --- .../__tests__/slickContextMenu.spec.ts | 4 ++-- .../common/src/extensions/slickContextMenu.ts | 15 +++++++-------- .../src/formatters/formatterUtilities.ts | 4 +++- .../slickgrid-vanilla-bundle.zip | Bin 551643 -> 571240 bytes 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts b/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts index f66d59fc0..d4d809a09 100644 --- a/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts +++ b/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts @@ -820,7 +820,7 @@ describe('ContextMenu Plugin', () => { it('should call "copyToClipboard" and get the value even when there is a "queryFieldNameGetterFn" callback defined with dot notation the command triggered is "copy"', () => { const copyGridOptionsMock = { ...gridOptionsMock, enableExcelExport: false, enableTextExport: false, contextMenu: { hideCopyCellValueCommand: false } } as GridOption; const columnMock = { id: 'firstName', name: 'First Name', field: 'firstName', queryFieldNameGetterFn: () => 'user.lastName' } as Column; - const dataContextMock = { id: 123, user: { firstName: 'John', lastName: 'Doe', age: 50 } }; + const dataContextMock = { id: 123, user: { firstName: '\u034f\u034fJohn', lastName: '\u034f\u034f Doe', age: 50 } }; jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(copyGridOptionsMock); const execSpy = jest.spyOn(window.document, 'execCommand'); plugin.dispose(); @@ -844,7 +844,7 @@ describe('ContextMenu Plugin', () => { it('should expect "itemUsabilityOverride" callback from the "copy" command to return True when a value to copy is found in the dataContext object', () => { const copyGridOptionsMock = { ...gridOptionsMock, enableExcelExport: false, enableTextExport: false, contextMenu: { hideCopyCellValueCommand: false } } as GridOption; const columnMock = { id: 'firstName', name: 'First Name', field: 'firstName' } as Column; - const dataContextMock = { id: 123, firstName: 'John', lastName: 'Doe', age: 50 }; + const dataContextMock = { id: 123, firstName: 'John', lastName: '·\u034f ⮞ Doe', age: 50 }; jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(copyGridOptionsMock); plugin.dispose(); plugin.init({ commandItems: [] }); diff --git a/packages/common/src/extensions/slickContextMenu.ts b/packages/common/src/extensions/slickContextMenu.ts index f5cef5b75..f722f6a74 100644 --- a/packages/common/src/extensions/slickContextMenu.ts +++ b/packages/common/src/extensions/slickContextMenu.ts @@ -381,13 +381,13 @@ export class SlickContextMenu extends MenuFromCellBaseClass { try { if (args && args.grid && args.command) { // get the value, if "exportWithFormatter" is set then we'll use the formatter output - const gridOptions = this.sharedService && this.sharedService.gridOptions || {}; - const cell = args && args.cell || 0; - const row = args && args.row || 0; + const gridOptions = this.sharedService?.gridOptions ?? {}; + const cell = args?.cell ?? 0; + const row = args?.row ?? 0; const columnDef = args?.column; const dataContext = args?.dataContext; - const grid = this.sharedService && this.sharedService.slickGrid; - const exportOptions = gridOptions && (gridOptions.excelExportOptions || { ...gridOptions.exportOptions, ...gridOptions.textExportOptions }); + const grid = this.sharedService?.slickGrid; + const exportOptions = gridOptions && ((gridOptions.excelExportOptions || { ...gridOptions.exportOptions, ...gridOptions.textExportOptions })); let textToCopy = exportWithFormatterWhenDefined(row, cell, columnDef, dataContext, grid, exportOptions); if (typeof columnDef.queryFieldNameGetterFn === 'function') { @@ -395,7 +395,7 @@ export class SlickContextMenu extends MenuFromCellBaseClass { } // remove any unwanted Tree Data/Grouping symbols from the beginning of the string before copying (e.g.: "⮟ Task 21" or "· Task 2") - const finalTextToCopy = textToCopy.replace(/^([·|⮞|⮟]\s*)|([·|⮞|⮟])\s*/g, ''); + const finalTextToCopy = textToCopy.replace(/^([\u00b7|\u034f|·|⮞|⮟]\s*)|([·|⮞|⮟])\s*/gi, '').replace(/[\u00b7|\u034f]/gi, '').trim(); // create fake