Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Do not escape double quotes when copying to clipboard #12734

Merged
merged 2 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ export const useGridCellSelection = (
cellData = serializeCellValue(cellParams, {
delimiterCharacter: clipboardCopyCellDelimiter,
ignoreValueFormatter,
shouldAppendQuotes: true,
shouldAppendQuotes: false,
});
} else {
cellData = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,30 @@ describe('<DataGridPremium /> - Clipboard', () => {
fireEvent.keyDown(cell, { key: 'c', keyCode: 67, ctrlKey: true });
expect(writeText.lastCall.firstArg).to.equal(['Adidas', 'Nike', 'Puma'].join('\r\n'));
});

it('should not escape double quotes when copying multiple cells to clipboard', () => {
render(
<DataGridPremium
columns={[{ field: 'value' }]}
rows={[
{ id: 0, value: '1 " 1' },
{ id: 1, value: '2' },
]}
unstable_cellSelection
disableRowSelectionOnClick
/>,
);

const cell = getCell(0, 0);
cell.focus();
userEvent.mousePress(cell);

fireEvent.keyDown(cell, { key: 'Ctrl' });
fireEvent.click(getCell(1, 0), { ctrlKey: true });

fireEvent.keyDown(cell, { key: 'c', keyCode: 67, ctrlKey: true });
expect(writeText.lastCall.firstArg).to.equal(['1 " 1', '2'].join('\r\n'));
});
});

describe('paste', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,17 @@ describe('<DataGridPro /> - Clipboard', () => {
apiRef={apiRef}
columns={columns}
rows={[
{
id: 0,
brand: 'Nike',
},
{
id: 1,
brand: 'Adidas',
},
{
id: 2,
brand: 'Puma',
},
{ id: 0, brand: 'Nike' },
{ id: 1, brand: 'Adidas' },
{ id: 2, brand: 'Puma' },
]}
{...props}
/>
</div>
);
}

describe('copySelectedRowsToClipboard', () => {
describe('copy to clipboard', () => {
let writeText: SinonStub;
const originalClipboard = navigator.clipboard;

Expand All @@ -74,5 +65,41 @@ describe('<DataGridPro /> - Clipboard', () => {
expect(writeText.firstCall.args[0]).to.equal(['0\tNike', '1\tAdidas'].join('\r\n'));
});
});

it('should not escape double quotes when copying a single cell to clipboard', () => {
render(
<Test
columns={[{ field: 'value' }]}
rows={[{ id: 0, value: '1 " 1' }]}
disableRowSelectionOnClick
/>,
);

const cell = getCell(0, 0);
cell.focus();
userEvent.mousePress(cell);

fireEvent.keyDown(cell, { key: 'c', keyCode: 67, ctrlKey: true });
expect(writeText.lastCall.firstArg).to.equal('1 " 1');
});

it('should not escape double quotes when copying rows to clipboard', () => {
render(
<Test
columns={[{ field: 'value' }]}
rows={[
{ id: 0, value: '1 " 1' },
{ id: 1, value: '2' },
]}
disableRowSelectionOnClick
/>,
);

act(() => apiRef.current.selectRows([0, 1]));
const cell = getCell(0, 0);
userEvent.mousePress(cell);
fireEvent.keyDown(cell, { key: 'c', keyCode: 67, ctrlKey: true });
expect(writeText.firstCall.args[0]).to.equal(['1 " 1', '2'].join('\r\n'));
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import { buildWarning } from '../../../../utils/warning';

function sanitizeCellValue(value: any, delimiterCharacter: string, shouldAppendQuotes: boolean) {
if (typeof value === 'string') {
// Make sure value containing delimiter or line break won't be split into multiple rows
if ([delimiterCharacter, '\n', '\r', '"'].some((delimiter) => value.includes(delimiter))) {
if (shouldAppendQuotes) {
return `"${value.replace(/"/g, '""')}"`;
if (shouldAppendQuotes) {
const escapedValue = value.replace(/"/g, '""');
// Make sure value containing delimiter or line break won't be split into multiple rows
if ([delimiterCharacter, '\n', '\r', '"'].some((delimiter) => value.includes(delimiter))) {
return `"${escapedValue}"`;
}
return `${value.replace(/"/g, '""')}`;
return escapedValue;
}

return value;
Expand Down