MCPcopy Create free account
hub / github.com/experdot/pointer / createRangeForMatch

Function createRangeForMatch

src/renderer/src/hooks/useSearchHighlight.ts:185–247  ·  view source on GitHub ↗

* 为单个匹配创建 Range

(
  container: HTMLElement,
  messages: ChatMessage[],
  match: SearchMatch
)

Source from the content-addressed store, hash-verified

183 * 为单个匹配创建 Range
184 */
185function createRangeForMatch(
186 container: HTMLElement,
187 messages: ChatMessage[],
188 match: SearchMatch
189): Range | null {
190 const messageEl = container.querySelector(`[data-message-id="${match.messageId}"]`)
191 if (!messageEl) return null
192
193 // 查找消息内容区域
194 const contentEl = messageEl.querySelector('.message-item__body')
195 if (!contentEl) return null
196
197 // 获取要匹配的文本
198 const messageContent = messages.find((m) => m.id === match.messageId)?.content ?? ''
199 const matchText = messageContent.slice(match.startOffset, match.endOffset)
200 if (!matchText) return null
201
202 // 收集所有文本节点
203 const textNodes: Text[] = []
204 const walker = document.createTreeWalker(contentEl, NodeFilter.SHOW_TEXT, null)
205 let node: Text | null
206 while ((node = walker.nextNode() as Text)) {
207 if (node.textContent) {
208 textNodes.push(node)
209 }
210 }
211
212 // 在文本节点中查找所有匹配位置
213 // 首先拼接所有文本节点的内容
214 let fullText = ''
215 const nodeOffsets: { node: Text; start: number; end: number }[] = []
216 for (const textNode of textNodes) {
217 const text = textNode.textContent ?? ''
218 nodeOffsets.push({
219 node: textNode,
220 start: fullText.length,
221 end: fullText.length + text.length
222 })
223 fullText += text
224 }
225
226 // 找到第 N 个匹配(根据 globalIndex 在该消息中的位置)
227 // 计算这是该消息中的第几个匹配
228 const matchIndexInMessage = countMatchesBefore(messages, match)
229
230 let currentMatchIndex = 0
231 let searchStartIndex = 0
232
233 while (true) {
234 const idx = fullText.indexOf(matchText, searchStartIndex)
235 if (idx === -1) break
236
237 if (currentMatchIndex === matchIndexInMessage) {
238 // 找到了目标匹配,创建 Range
239 return createRangeFromFullTextOffset(nodeOffsets, idx, idx + matchText.length)
240 }
241
242 currentMatchIndex++

Callers 1

useSearchHighlightFunction · 0.85

Calls 2

countMatchesBeforeFunction · 0.85

Tested by

no test coverage detected