From 0b274efa0f740e1da9e4ee5ab5a5807b7ed27a50 Mon Sep 17 00:00:00 2001 From: JaeHyung Jang Date: Sun, 12 Apr 2026 21:02:20 +0900 Subject: [PATCH] fix(export): preserve unicode characters in workflow filenames Previously, Non-ASCII characters (like Korean) in workflow names were replaced by dashes during export because of a restrictive regex. This update uses a Unicode-aware regex to allow letters and numbers from any language while still sanitizing unsafe filesystem characters. fixes #4119 Signed-off-by: JaeHyung Jang --- .../operations/import-export.test.ts | 33 +++++++++++++++++++ .../lib/workflows/operations/import-export.ts | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 apps/sim/lib/workflows/operations/import-export.test.ts diff --git a/apps/sim/lib/workflows/operations/import-export.test.ts b/apps/sim/lib/workflows/operations/import-export.test.ts new file mode 100644 index 00000000000..7d913327274 --- /dev/null +++ b/apps/sim/lib/workflows/operations/import-export.test.ts @@ -0,0 +1,33 @@ +/** + * @vitest-environment node + */ +import { describe, expect, it } from 'vitest' +import { sanitizePathSegment } from '@/lib/workflows/operations/import-export' + +describe('sanitizePathSegment', () => { + it('should preserve ASCII alphanumeric characters', () => { + expect(sanitizePathSegment('workflow-123_abc')).toBe('workflow-123_abc') + }) + + it('should replace spaces with dashes', () => { + expect(sanitizePathSegment('my workflow')).toBe('my-workflow') + }) + + it('should replace special characters with dashes', () => { + expect(sanitizePathSegment('workflow!@#')).toBe('workflow-') + }) + + it('should preserve Korean characters (BUG REPRODUCTION)', () => { + expect(sanitizePathSegment('한글')).toBe('한글') + }) + + it('should preserve other Unicode characters', () => { + expect(sanitizePathSegment('日本語')).toBe('日本語') + }) + + it('should remove filesystem unsafe characters', () => { + expect(sanitizePathSegment('work/flow?name*')).not.toContain('/') + expect(sanitizePathSegment('work/flow?name*')).not.toContain('?') + expect(sanitizePathSegment('work/flow?name*')).not.toContain('*') + }) +}) diff --git a/apps/sim/lib/workflows/operations/import-export.ts b/apps/sim/lib/workflows/operations/import-export.ts index fdac248f134..093f3617a9f 100644 --- a/apps/sim/lib/workflows/operations/import-export.ts +++ b/apps/sim/lib/workflows/operations/import-export.ts @@ -48,7 +48,7 @@ export interface WorkspaceExportStructure { * Sanitizes a string for use as a path segment in a ZIP file. */ export function sanitizePathSegment(name: string): string { - return name.replace(/[^a-z0-9-_]/gi, '-') + return name.replace(/[^\p{L}\p{N}\-_]/gu, '-').replace(/-+/g, '-') } /**