本地搜索使用json替换xml,速度更快

## xml文件格式本地测试
![](https://cdn.jsdelivr.net/gh/Rr210/image@master/hexo/api/20211006095512.png)
## json文件本地测试
![](https://cdn.jsdelivr.net/gh/Rr210/image@master/hexo/api/20211006095847.png)
## json文件线上测试
![](https://cdn.jsdelivr.net/gh/Rr210/image@master/hexo/api/20211006100635.png)
## 模式切换
两种模式 切换 只需要修改全局配置文件的搜索插件文件格式(json/xml)
This commit is contained in:
Harry
2021-10-06 14:52:52 +08:00
committed by GitHub
parent 7e729cff79
commit 312a766901

View File

@@ -10,7 +10,7 @@ window.addEventListener('load', () => {
loadFlag = true loadFlag = true
} }
// shortcut: ESC // shortcut: ESC
document.addEventListener('keydown', function f (event) { document.addEventListener('keydown', function f(event) {
if (event.code === 'Escape') { if (event.code === 'Escape') {
closeSearch() closeSearch()
document.removeEventListener('keydown', f) document.removeEventListener('keydown', f)
@@ -41,107 +41,112 @@ window.addEventListener('load', () => {
searchClickFn() searchClickFn()
}) })
function search (path) { async function search(path) {
fetch(GLOBAL_CONFIG.root + path) let datas = []
.then(response => response.text()) const typeF = path.split('.')[1]
.then(str => new window.DOMParser().parseFromString(str, 'text/xml')) const response = await fetch(GLOBAL_CONFIG.root + path)
.then(data => { if (typeF === 'json') {
const datas = [...data.querySelectorAll('entry')].map(function (item) { datas = await response.json()
const content = item.querySelector('content') } else if (typeF === 'xml') {
return { let res = await response.text()
title: item.querySelector('title').textContent, let t = await new window.DOMParser().parseFromString(res, 'text/xml')
content: content ? content.textContent : '', let a = await t
url: item.querySelector('url').textContent datas = [...a.querySelectorAll('entry')].map(function (item) {
} return {
}) title: item.querySelector('title').textContent,
content: item.querySelector('content').textContent,
const $input = document.querySelector('#local-search-input input') url: item.querySelector('url').textContent
const $resultContent = document.getElementById('local-search-results') }
$input.addEventListener('input', function () { })
let str = '<div class="search-result-list">' }
const keywords = this.value.trim().toLowerCase().split(/[\s]+/) const $input = document.querySelector('#local-search-input input')
$resultContent.innerHTML = '' const $resultContent = document.getElementById('local-search-results')
if (this.value.trim().length <= 0) return $input.addEventListener('input', function () {
let count = 0 let str = '<div class="search-result-list">'
// perform local searching const keywords = this.value.trim().toLowerCase().split(/[\s]+/)
datas.forEach(function (data) { $resultContent.innerHTML = ''
let isMatch = true if (this.value.trim().length <= 0) return
if (!data.title || data.title.trim() === '') { let count = 0
data.title = 'Untitled' // perform local searching
} datas.forEach(function (data) {
let dataTitle = data.title.trim().toLowerCase() let isMatch = true
const dataContent = data.content.trim().replace(/<[^>]+>/g, '').toLowerCase() if (!data.title || data.title.trim() === '') {
const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url data.title = 'Untitled'
let indexTitle = -1 }
let indexContent = -1 let dataTitle = data.title.trim().toLowerCase()
let firstOccur = -1 const dataContent = data.content.trim().replace(/<[^>]+>/g, '').toLowerCase()
// only match artiles with not empty titles and contents const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url
if (dataTitle !== '' || dataContent !== '') { let indexTitle = -1
keywords.forEach(function (keyword, i) { let indexContent = -1
indexTitle = dataTitle.indexOf(keyword) let firstOccur = -1
indexContent = dataContent.indexOf(keyword) // only match artiles with not empty titles and contents
if (indexTitle < 0 && indexContent < 0) { if (dataTitle !== '' || dataContent !== '') {
isMatch = false keywords.forEach(function (keyword, i) {
} else { indexTitle = dataTitle.indexOf(keyword)
if (indexContent < 0) { indexContent = dataContent.indexOf(keyword)
indexContent = 0 if (indexTitle < 0 && indexContent < 0) {
}
if (i === 0) {
firstOccur = indexContent
}
}
})
} else {
isMatch = false isMatch = false
} } else {
if (indexContent < 0) {
// show search results indexContent = 0
if (isMatch) { }
const content = data.content.trim().replace(/<[^>]+>/g, '') if (i === 0) {
if (firstOccur >= 0) { firstOccur = indexContent
// cut out 130 characters
let start = firstOccur - 30
let end = firstOccur + 100
if (start < 0) {
start = 0
}
if (start === 0) {
end = 100
}
if (end > content.length) {
end = content.length
}
let matchContent = content.substring(start, end)
// highlight all keywords
keywords.forEach(function (keyword) {
const regS = new RegExp(keyword, 'gi')
matchContent = matchContent.replace(regS, '<span class="search-keyword">' + keyword + '</span>')
dataTitle = dataTitle.replace(regS, '<span class="search-keyword">' + keyword + '</span>')
})
str += '<div class="local-search__hit-item"><a href="' + dataUrl + '" class="search-result-title">' + dataTitle + '</a>'
count += 1
if (dataContent !== '') {
str += '<p class="search-result">' + matchContent + '...</p>'
}
} }
str += '</div>'
} }
}) })
if (count === 0) { } else {
str += '<div id="local-search__hits-empty">' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) + isMatch = false
'</div>' }
// show search results
if (isMatch) {
const content = data.content.trim().replace(/<[^>]+>/g, '')
if (firstOccur >= 0) {
// cut out 130 characters
// let start = firstOccur - 30 < 0 ? 0 : firstOccur - 30
// let end = firstOccur + 50 > content.length ? content.length : firstOccur + 50
let start = firstOccur - 30
let end = firstOccur + 100
if (start < 0) {
start = 0
}
if (start === 0) {
end = 100
}
if (end > content.length) {
end = content.length
}
let matchContent = content.substring(start, end)
// highlight all keywords
keywords.forEach(function (keyword) {
const regS = new RegExp(keyword, 'gi')
matchContent = matchContent.replace(regS, '<span class="search-keyword">' + keyword + '</span>')
dataTitle = dataTitle.replace(regS, '<span class="search-keyword">' + keyword + '</span>')
})
str += '<div class="local-search__hit-item"><a href="' + dataUrl + '" class="search-result-title">' + dataTitle + '</a>'
count += 1
if (dataContent !== '') {
str += '<p class="search-result">' + matchContent + '...</p>'
}
} }
str += '</div>' str += '</div>'
$resultContent.innerHTML = str }
window.pjax && window.pjax.refresh($resultContent)
})
}) })
if (count === 0) {
str += '<div id="local-search__hits-empty">' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) +
'</div>'
}
str += '</div>'
$resultContent.innerHTML = str
window.pjax && window.pjax.refresh($resultContent)
})
} }
}) })