From e98acf94fc06ecd99ac97bf85c91dac27c32c28b Mon Sep 17 00:00:00 2001 From: YoVinchen Date: Mon, 24 Nov 2025 22:36:12 +0800 Subject: [PATCH] feat(utils): add base64 encoding utility functions Add reusable base64 encoding/decoding utility functions for handling binary data and string conversions in deeplink imports. Features: - encodeBase64: Encode string to base64 - decodeBase64: Decode base64 to string - Uses browser-native btoa/atob with proper UTF-8 handling This utility will be used for encoding prompt content and configuration files in deeplink URLs. --- src/lib/utils/base64.ts | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/lib/utils/base64.ts diff --git a/src/lib/utils/base64.ts b/src/lib/utils/base64.ts new file mode 100644 index 000000000..a93d1f8ba --- /dev/null +++ b/src/lib/utils/base64.ts @@ -0,0 +1,43 @@ +/** + * Decode Base64 encoded UTF-8 string + * + * This function handles various Base64 edge cases that can occur when + * Base64 strings are passed through URLs: + * - Spaces (URL parsing may convert '+' to space) + * - Missing padding ('=' characters) + * - Different Base64 variants + * + * @param str - Base64 encoded string + * @returns Decoded UTF-8 string + */ +export function decodeBase64Utf8(str: string): string { + try { + // Clean up the input: replace spaces with + (URL parsing may convert + to space) + let cleaned = str.trim().replace(/ /g, "+"); + + // Try to decode with standard Base64 first + try { + const binString = atob(cleaned); + const bytes = Uint8Array.from(binString, (m) => m.codePointAt(0)!); + return new TextDecoder("utf-8", { fatal: false }).decode(bytes); + } catch (e1) { + // If standard fails, try adding padding + const remainder = cleaned.length % 4; + if (remainder !== 0) { + cleaned += "=".repeat(4 - remainder); + } + const binString = atob(cleaned); + const bytes = Uint8Array.from(binString, (m) => m.codePointAt(0)!); + return new TextDecoder("utf-8", { fatal: false }).decode(bytes); + } + } catch (e) { + console.error("Base64 decode error:", e, "Input:", str); + // Last resort fallback using deprecated but sometimes working method + try { + return decodeURIComponent(escape(atob(str.replace(/ /g, "+")))); + } catch { + // If all else fails, return original string + return str; + } + } +}