word 搜索优化
This commit is contained in:
parent
48dd413f87
commit
5be02d46fd
|
|
@ -176,6 +176,33 @@ export default {
|
||||||
return (element.textContent || '').trim()
|
return (element.textContent || '').trim()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getSearchableTextContent(element) {
|
||||||
|
if (!element) return ''
|
||||||
|
let text = ''
|
||||||
|
const walker = document.createTreeWalker(
|
||||||
|
element,
|
||||||
|
NodeFilter.SHOW_TEXT,
|
||||||
|
{
|
||||||
|
acceptNode: (node) => {
|
||||||
|
const parent = node.parentElement
|
||||||
|
if (!parent) return NodeFilter.FILTER_REJECT
|
||||||
|
const tagName = parent.tagName ? parent.tagName.toLowerCase() : ''
|
||||||
|
if (tagName === 'mark' || tagName === 'script' || tagName === 'style' || tagName === 'noscript') {
|
||||||
|
return NodeFilter.FILTER_REJECT
|
||||||
|
}
|
||||||
|
return NodeFilter.FILTER_ACCEPT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let node
|
||||||
|
while ((node = walker.nextNode())) {
|
||||||
|
if (node.textContent) {
|
||||||
|
text += node.textContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
},
|
||||||
|
|
||||||
prepareSearchSegments(forceReset = false) {
|
prepareSearchSegments(forceReset = false) {
|
||||||
if (!this.docRendered) {
|
if (!this.docRendered) {
|
||||||
if (forceReset) {
|
if (forceReset) {
|
||||||
|
|
@ -270,7 +297,7 @@ export default {
|
||||||
highlightTextInNode(node, pattern, results, segmentIndex, parentElement, markIndexRef) {
|
highlightTextInNode(node, pattern, results, segmentIndex, parentElement, markIndexRef) {
|
||||||
if (node.nodeType === Node.TEXT_NODE) {
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
const text = node.textContent
|
const text = node.textContent
|
||||||
if (!text || !text.trim()) return
|
if (!text) return
|
||||||
|
|
||||||
pattern.lastIndex = 0
|
pattern.lastIndex = 0
|
||||||
const textMatches = []
|
const textMatches = []
|
||||||
|
|
@ -355,17 +382,9 @@ export default {
|
||||||
|
|
||||||
const results = []
|
const results = []
|
||||||
let totalTextMatches = 0
|
let totalTextMatches = 0
|
||||||
|
const segmentMatchCounts = []
|
||||||
|
|
||||||
this.searchSegments.forEach((el, segmentIndex) => {
|
this.searchSegments.forEach((el, segmentIndex) => {
|
||||||
const originalText = el.dataset.originalText
|
|
||||||
if (typeof originalText === 'undefined' || !originalText) return
|
|
||||||
|
|
||||||
pattern.lastIndex = 0
|
|
||||||
const textMatchCount = (originalText.match(pattern) || []).length
|
|
||||||
if (textMatchCount === 0) return
|
|
||||||
|
|
||||||
totalTextMatches += textMatchCount
|
|
||||||
|
|
||||||
const originalHtml = el.dataset.originalHtml
|
const originalHtml = el.dataset.originalHtml
|
||||||
if (typeof originalHtml === 'undefined') return
|
if (typeof originalHtml === 'undefined') return
|
||||||
|
|
||||||
|
|
@ -373,25 +392,47 @@ export default {
|
||||||
el.innerHTML = cleanHtml
|
el.innerHTML = cleanHtml
|
||||||
el.dataset.originalHtml = cleanHtml
|
el.dataset.originalHtml = cleanHtml
|
||||||
|
|
||||||
|
const searchableText = this.getSearchableTextContent(el)
|
||||||
|
if (!searchableText) return
|
||||||
|
|
||||||
|
pattern.lastIndex = 0
|
||||||
|
const textMatchCount = (searchableText.match(pattern) || []).length
|
||||||
|
if (textMatchCount === 0) return
|
||||||
|
|
||||||
|
totalTextMatches += textMatchCount
|
||||||
|
|
||||||
const existingMarks = el.querySelectorAll('mark')
|
const existingMarks = el.querySelectorAll('mark')
|
||||||
if (existingMarks.length > 0) {
|
if (existingMarks.length > 0) {
|
||||||
console.warn(`Segment ${segmentIndex} still has ${existingMarks.length} mark tags after cleaning`)
|
console.warn(`Segment ${segmentIndex} still has ${existingMarks.length} mark tags after cleaning`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const markIndexRef = { value: 0 }
|
const markIndexRef = { value: 0 }
|
||||||
|
const beforeHighlightText = this.getSearchableTextContent(el)
|
||||||
const children = Array.from(el.childNodes)
|
const children = Array.from(el.childNodes)
|
||||||
children.forEach(child => {
|
children.forEach(child => {
|
||||||
this.highlightTextInNode(child, pattern, results, segmentIndex, el, markIndexRef)
|
this.highlightTextInNode(child, pattern, results, segmentIndex, el, markIndexRef)
|
||||||
})
|
})
|
||||||
|
|
||||||
const createdMarks = el.querySelectorAll('mark.search-highlight')
|
const createdMarks = el.querySelectorAll('mark.search-highlight')
|
||||||
if (createdMarks.length !== textMatchCount) {
|
const actualCount = createdMarks.length
|
||||||
console.warn(`Segment ${segmentIndex}: expected ${textMatchCount} marks, created ${createdMarks.length}`)
|
const afterHighlightText = this.getSearchableTextContent(el)
|
||||||
|
|
||||||
|
segmentMatchCounts.push({
|
||||||
|
segmentIndex,
|
||||||
|
expected: textMatchCount,
|
||||||
|
actual: actualCount,
|
||||||
|
searchableTextLength: searchableText.length,
|
||||||
|
beforeHighlightLength: beforeHighlightText.length,
|
||||||
|
afterHighlightLength: afterHighlightText.length
|
||||||
|
})
|
||||||
|
|
||||||
|
if (actualCount !== textMatchCount) {
|
||||||
|
console.warn(`Segment ${segmentIndex}: expected ${textMatchCount} marks, created ${actualCount}. Text: "${searchableText.substring(0, 100)}..."`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (results.length !== totalTextMatches) {
|
if (results.length !== totalTextMatches) {
|
||||||
console.warn(`Total matches mismatch: expected ${totalTextMatches}, got ${results.length}`)
|
console.warn(`Total matches mismatch: expected ${totalTextMatches}, got ${results.length}`, segmentMatchCounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.searchResults = results
|
this.searchResults = results
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue