(() => {
fetch('/index.json')
.then(response => response.json())
.then(data => {
const fuse = new Fuse(data, {
keys: ['title', 'content'],
shouldSort: true,
includeMatches: true,
minMatchCharLength: 2,
threshold: 0.0,
ignoreLocation: true,
})
document.getElementById('search-form').addEventListener('submit', function (e) {
e.preventDefault();
const data = new FormData(e.target)
// data.entries() returns iterator, [...data.entries()] returns [["q", "input"]]
const input = [...data.entries()][0][1]
const results = fuse.search(input)
displayResults(input, results)
});
});
})();
function displayResults(input, results) {
const searchResults = document.getElementById('search-result');
searchResults.setAttribute('style', 'display: block;')
searchResults.nextElementSibling.setAttribute('style', 'display: none;')
let html = renderResultsCountHtml(results.length, input)
if (results.length > 0) {
let li = renderResultsItemHtml(results)
html += `
`
}
searchResults.innerHTML = html
}
function renderResultsCountHtml(count, input) {
let html = `
${count}
results
for "${input}"
`
return html
}
function renderResultsItemHtml(results) {
// modified from https://github.com/brunocechet/Fuse.js-with-highlight
var highlighter = function(resultItem){
resultItem.matches.forEach((matchItem) => {
var text = resultItem.item[matchItem.key];
var result = []
var matches = [].concat(matchItem.indices);
var pair = matches.shift()
for (var i = 0; i < text.length; i++) {
var char = text.charAt(i)
if (pair && i == pair[0]) {
result.push('')
}
result.push(char)
if (pair && i == pair[1]) {
result.push('')
pair = matches.shift()
}
}
resultItem.highlight = result.join('');
if(resultItem.children && resultItem.children.length > 0){
resultItem.children.forEach((child) => {
highlighter(child);
});
}
});
};
let html = ``
results.forEach(result => {
highlighter(result)
// truncated highlight content
let truncated = result.highlight.substring(0, 2000)
const reg = /([a-zA-Z0-9\u4e00-\u9fa5]+<\/span>)/g
let array = truncated.split(reg)
// drop unstable part
array.pop()
let content = ""
if (array.length > 0) {
content = array.join('')
} else {
// fallback to no highlighted truncated content
content = result.item.content.substring(0, 2000)
}
html += `
`
})
return html
}