* 从字符串中提取 avatars 对象内容 * 正确处理 JSON 字符串中的花括号匹配(考虑字符串内的转义字符)
(content: string)
| 279 | * 正确处理 JSON 字符串中的花括号匹配(考虑字符串内的转义字符) |
| 280 | */ |
| 281 | function extractAvatarsObject(content: string): string | null { |
| 282 | const searchStr = '"avatars":' |
| 283 | const startIdx = content.indexOf(searchStr) |
| 284 | if (startIdx === -1) return null |
| 285 | |
| 286 | let i = startIdx + searchStr.length |
| 287 | // 跳过空白字符 |
| 288 | while (i < content.length && /\s/.test(content[i])) i++ |
| 289 | |
| 290 | if (content[i] !== '{') return null |
| 291 | |
| 292 | // 从 { 开始匹配 |
| 293 | let braceDepth = 0 |
| 294 | let inString = false |
| 295 | let escape = false |
| 296 | const objStart = i |
| 297 | |
| 298 | for (; i < content.length; i++) { |
| 299 | const char = content[i] |
| 300 | |
| 301 | if (escape) { |
| 302 | escape = false |
| 303 | continue |
| 304 | } |
| 305 | |
| 306 | if (char === '\\' && inString) { |
| 307 | escape = true |
| 308 | continue |
| 309 | } |
| 310 | |
| 311 | if (char === '"') { |
| 312 | inString = !inString |
| 313 | continue |
| 314 | } |
| 315 | |
| 316 | if (!inString) { |
| 317 | if (char === '{') braceDepth++ |
| 318 | if (char === '}') { |
| 319 | braceDepth-- |
| 320 | if (braceDepth === 0) { |
| 321 | return content.slice(objStart, i + 1) |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | return null |
| 328 | } |
| 329 | |
| 330 | try { |
| 331 | // 先尝试从文件头解析(适用于成员较少的聊天) |