(renderedText: string, oldSubstring: string, textAnchor: TextEditAnchor)
| 1381 | } |
| 1382 | |
| 1383 | function resolveAnchoredStart(renderedText: string, oldSubstring: string, textAnchor: TextEditAnchor): number | null { |
| 1384 | const oldLength = textAnchor.end - textAnchor.start; |
| 1385 | if (anchorMatchesAt(renderedText, textAnchor.start, oldSubstring, textAnchor)) { |
| 1386 | return textAnchor.start; |
| 1387 | } |
| 1388 | |
| 1389 | const maxStart = renderedText.length - oldLength; |
| 1390 | const candidates: number[] = []; |
| 1391 | for (let start = 0; start <= maxStart; start++) { |
| 1392 | if (anchorMatchesAt(renderedText, start, oldSubstring, textAnchor)) { |
| 1393 | candidates.push(start); |
| 1394 | } |
| 1395 | } |
| 1396 | |
| 1397 | if (candidates.length === 0) { |
| 1398 | if (!oldSubstring && textAnchor.start >= 0 && textAnchor.start <= renderedText.length) { |
| 1399 | return textAnchor.start; |
| 1400 | } |
| 1401 | if ( |
| 1402 | oldSubstring && |
| 1403 | textAnchor.start >= 0 && |
| 1404 | textAnchor.start + oldLength <= renderedText.length && |
| 1405 | renderedText.slice(textAnchor.start, textAnchor.start + oldLength) === oldSubstring |
| 1406 | ) { |
| 1407 | return textAnchor.start; |
| 1408 | } |
| 1409 | return null; |
| 1410 | } |
| 1411 | |
| 1412 | if (candidates.length === 1) return candidates[0]; |
| 1413 | |
| 1414 | return candidates.reduce((best, candidate) => { |
| 1415 | const bestDistance = Math.abs(best - textAnchor.start); |
| 1416 | const candidateDistance = Math.abs(candidate - textAnchor.start); |
| 1417 | return candidateDistance < bestDistance ? candidate : best; |
| 1418 | }); |
| 1419 | } |
| 1420 | |
| 1421 | function replaceWithinSingleSegmentAtOffset( |
| 1422 | node: any, |
no test coverage detected