( node: Text, x: number, y: number, start: number, end: number, length: number, )
| 218 | * |
| 219 | */ |
| 220 | export const getTextOffset = ( |
| 221 | node: Text, |
| 222 | x: number, |
| 223 | y: number, |
| 224 | start: number, |
| 225 | end: number, |
| 226 | length: number, |
| 227 | ): number => { |
| 228 | const range = document.createRange() |
| 229 | if (end - start > 1) { |
| 230 | const mid = Math.floor((start + end) / 2) |
| 231 | try { |
| 232 | range.setStart(node, mid) |
| 233 | range.setEnd(node, Math.max(Math.min(mid, length), 0)) |
| 234 | } catch (e) { |
| 235 | return start |
| 236 | } |
| 237 | const rects = range.getClientRects() |
| 238 | if (rects.length === 0) { |
| 239 | return start |
| 240 | } |
| 241 | for (const rect of rects) { |
| 242 | if (y < rect.top) { |
| 243 | return getTextOffset(node, x, y, start, mid, length) |
| 244 | } else if (y > rect.bottom) { |
| 245 | return getTextOffset(node, x, y, mid, end, length) |
| 246 | } else if (x <= rect.left + rect.width) { |
| 247 | return getTextOffset(node, x, y, start, mid, length) |
| 248 | } |
| 249 | } |
| 250 | return getTextOffset(node, x, y, mid, end, length) |
| 251 | } |
| 252 | const [rStart, rEnd] = getCharRange(node.textContent || '', start) |
| 253 | try { |
| 254 | range.setStart(node, rStart) |
| 255 | range.setEnd(node, Math.max(Math.min(rEnd, length), 0)) |
| 256 | } catch (err) { |
| 257 | return rStart |
| 258 | } |
| 259 | const rects = range.getClientRects() |
| 260 | if (rects.length === 0) return rStart |
| 261 | |
| 262 | for (const rect of rects) { |
| 263 | if (rect.width === 0) continue |
| 264 | if (y < rect.top) { |
| 265 | return rStart |
| 266 | } else if (y > rect.bottom) { |
| 267 | return rEnd |
| 268 | } else if (x <= rect.left + rect.width / 2) { |
| 269 | return rStart |
| 270 | } |
| 271 | } |
| 272 | return rEnd |
| 273 | } |
no test coverage detected
searching dependent graphs…