| 305 | * @returns The content string with the transformed JSON field |
| 306 | */ |
| 307 | export function transformJsonInString<T = unknown>( |
| 308 | content: string, |
| 309 | field: string, |
| 310 | transform: (json: T) => unknown, |
| 311 | fallback: string, |
| 312 | ): string { |
| 313 | // Use a non-greedy match for objects/arrays to prevent over-matching |
| 314 | const pattern = new RegExp(`"${field}"\\s*:\\s*(\\{[^}]*?\\}|\\[[^\\]]*?\\])`) |
| 315 | const match = content.match(pattern) |
| 316 | |
| 317 | if (!match) { |
| 318 | return content |
| 319 | } |
| 320 | |
| 321 | try { |
| 322 | const json = JSON.parse(match[1]) |
| 323 | const transformed = transform(json) |
| 324 | |
| 325 | // Important: Only replace the exact matched portion to prevent duplicates |
| 326 | return content.replace( |
| 327 | match[0], |
| 328 | `"${field}":${JSON.stringify(transformed)}`, |
| 329 | ) |
| 330 | } catch (error) { |
| 331 | // Only replace the exact matched portion even in error case |
| 332 | return content.replace(match[0], `"${field}":${fallback}`) |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | /** |
| 337 | * Generates a compact unique identifier by combining timestamp bits with random bits. |