fix: use json-2-csv built-in excelBOM option for UTF-8 BOM support

Instead of manually prepending \uFEFF to the Blob, use the library's
built-in excelBOM option which handles BOM prepending at the CSV
generation level. This is cleaner and ensures BOM is included regardless
of how the CSV string is consumed downstream.

Fixes #19230

https://claude.ai/code/session_01DXL7ohePLgJoWVSBWU5Cgm
This commit is contained in:
Claude
2026-04-02 16:30:34 +00:00
parent 331c223e73
commit 595b0e6abc
2 changed files with 43 additions and 1 deletions
@@ -63,7 +63,7 @@ describe('generateCsv', () => {
];
const csv = generateCsv({ columns, rows });
expect(csv)
.toEqual(`Id,Foo,Empty,Nested link field / Link URL,Nested link field / Secondary Links,Relation
.toEqual(`\uFEFFId,Foo,Empty,Nested link field / Link URL,Nested link field / Secondary Links,Relation
1,some field,,https://www.test.com,"[{""label"":""secondary link 1"",""url"":""https://www.test.com""},{""label"":""secondary link 2"",""url"":""https://www.test.com""}]",a relation`);
});
@@ -166,6 +166,47 @@ describe('generateCsv', () => {
expect(csv).toContain('1,John Doe,[],[]');
});
it('prepends UTF-8 BOM for Excel compatibility', () => {
const columns: Pick<
ColumnDefinition<FieldMetadata>,
'size' | 'label' | 'type' | 'metadata'
>[] = [
{
label: 'Name',
size: 100,
type: FieldMetadataType.TEXT,
metadata: { fieldName: 'name' },
},
];
const csv = generateCsv({ columns, rows: [{ id: '1', name: 'test' }] });
expect(csv.charCodeAt(0)).toBe(0xfeff);
});
it.each([
['Arabic', 'مرحبا'],
['Chinese', '你好'],
['Japanese', 'こんにちは'],
['Korean', '안녕하세요'],
])('preserves %s characters in generated CSV', (_, name) => {
const columns: Pick<
ColumnDefinition<FieldMetadata>,
'size' | 'label' | 'type' | 'metadata'
>[] = [
{
label: 'Name',
size: 100,
type: FieldMetadataType.TEXT,
metadata: { fieldName: 'name' },
},
];
const csv = generateCsv({ columns, rows: [{ id: '1', name }] });
expect(csv).toContain(name);
});
describe('CSV Injection Prevention with ZWJ', () => {
it('prevents formula injection with equals sign using ZWJ prefix', () => {
const columns: Pick<
@@ -114,6 +114,7 @@ export const generateCsv: GenerateExport = ({
return json2csv(sanitizedRows, {
keys,
emptyFieldValue: '',
excelBOM: true,
// Note: We handle CSV injection prevention manually with ZWJ approach above
// This preserves original which the csvSecurity option does not do
});