diff --git a/packages/editor-ui/src/utils/__tests__/mappingUtils.test.ts b/packages/editor-ui/src/utils/__tests__/mappingUtils.test.ts index 224b00be560be..8dfc75ba1ba83 100644 --- a/packages/editor-ui/src/utils/__tests__/mappingUtils.test.ts +++ b/packages/editor-ui/src/utils/__tests__/mappingUtils.test.ts @@ -216,19 +216,19 @@ describe('Mapping Utils', () => { expect(result).toBe("{{ $('nodeName').item.json.sample[0].path }}"); }); - it('should generate a mapped expression with special characters in array path', () => { + it('should generate a mapped expression with invalid identifier names in array path', () => { const input = { nodeName: 'nodeName', distanceFromActive: 2, - path: ['sample', 'path with-space', 'path-with-hyphen'], + path: ['sample', 'path with-space', 'path-with-hyphen', '2iStartWithANumber'], }; const result = getMappedExpression(input); expect(result).toBe( - "{{ $('nodeName').item.json.sample['path with-space']['path-with-hyphen'] }}", + "{{ $('nodeName').item.json.sample['path with-space']['path-with-hyphen']['2iStartWithANumber'] }}", ); }); - it('should handle paths with special characters', () => { + it('should handle paths with invalid identifier names', () => { const input = { nodeName: 'nodeName', distanceFromActive: 2, @@ -243,11 +243,12 @@ describe('Mapping Utils', () => { 'test,', 'test:', 'path.', + '2iStartWithANumber', ], }; const result = getMappedExpression(input); expect(result).toBe( - "{{ $('nodeName').item.json.sample['\"Execute\"']['`Execute`']['\\'Execute\\'']['[Execute]']['{Execute}']['execute?']['test,']['test:']['path.'] }}", + "{{ $('nodeName').item.json.sample['\"Execute\"']['`Execute`']['\\'Execute\\'']['[Execute]']['{Execute}']['execute?']['test,']['test:']['path.']['2iStartWithANumber'] }}", ); }); diff --git a/packages/editor-ui/src/utils/mappingUtils.ts b/packages/editor-ui/src/utils/mappingUtils.ts index 35e524c88890d..b743f2265d474 100644 --- a/packages/editor-ui/src/utils/mappingUtils.ts +++ b/packages/editor-ui/src/utils/mappingUtils.ts @@ -1,17 +1,20 @@ import type { INodeProperties, NodeParameterValueType } from 'n8n-workflow'; import { isResourceLocatorValue } from 'n8n-workflow'; +const validJsIdNameRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; + +function isValidJsIdentifierName(name: string | number): boolean { + return validJsIdNameRegex.test(name.toString()); +} + export function generatePath(root: string, path: Array): string { return path.reduce((accu: string, part: string | number) => { if (typeof part === 'number') { return `${accu}[${part}]`; } - const special = ['-', ' ', '.', "'", '"', '`', '[', ']', '{', '}', '(', ')', ':', ',', '?']; - const hasSpecial = !!special.find((s) => part.includes(s)); - if (hasSpecial) { - const escaped = part.replaceAll("'", "\\'"); - return `${accu}['${escaped}']`; + if (!isValidJsIdentifierName(part)) { + return `${accu}['${escapeMappingString(part)}']`; } return `${accu}.${part}`;