hexo-theme-sukax
Version:
Modern, powerful and simple theme for Hexo
174 lines (152 loc) • 7.53 kB
JavaScript
/*!
* Hexo Theme Suka | local-search.js
* Author: SukkaW
* Link: https://github.com/SukkaW/hexo-theme-suka
* License: GPL-3.0
*/
(function () {
window.getParameterByName = function (name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(window.location.search);
return results == null ? '' : decodeURIComponent(results[1]);
}
var searchKeyword = window.getParameterByName('s');
window.searchEscape = function (keyword) {
var htmlEntityMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
'\'': ''',
'/': '/'
};
return keyword.replace(/[&<>"'/]/g, function (i) {
return htmlEntityMap[i];
});
}
window.searchFunc = function (searchFilePath, noResultText) {
'use strict';
fetch(searchFilePath).then(function (res) {
return res.json();
}).then(function (datas) {
var $resultContent = document.getElementById('search-output');
var $resultNum = document.getElementById('search-result-num');
var $resultInfo = document.getElementById('search-result-info');
var resultArray = [];
function search(key) {
var parseKeywords = function () {
var input = key.trim().toLowerCase().split(/[\s\-]+/);
var output = [];
for (var i in input) {
var keyword = input[i];
if (keyword.indexOf('+') > -1) {
var keys = keyword.split('+');
for (var j in keys) {
output.push(keys[j]);
}
} else {
output.push(keyword);
}
}
return output;
}
var keywords = parseKeywords();
window.searchKeyword = keywords;
var index_num = 0;
$resultContent.innerHTML = '';
if (key.trim().length <= 0) return;
// perform local searching
datas.forEach(function (data) {
if (typeof data.title === 'undefined') return;
if (typeof data.content === 'undefined') return;
var isMatch = true;
var data_title = data.title.trim().toLowerCase();
var data_date = new Date(data.date).toLocaleDateString();
var data_tags = (typeof data.tags !== 'undefined') ? data.tags : [];
var data_content = data.content.trim().replace(/<[^>]+>/g, '').toLowerCase();
var index_title = -1;
var index_tags = -1;
var index_content = -1;
var first_occur = -1;
var data_weight = 0;
// only match artiles with not empty titles and contents
if (data_title !== '' && data_content !== '') {
keywords.forEach(function (keyword, i) {
index_title = data_title.indexOf(keyword);
index_tags = data_tags.indexOf(keyword);
index_content = data_content.indexOf(keyword);
if (index_title < 0 && index_tags < 0 && index_content < 0) {
isMatch = false;
} else {
if (index_title >= 0) data_weight = data_weight + 4;
if (index_tags >= 0) data_weight = data_weight + 2;
if (index_content >= 0) data_weight = data_weight + 1;
if (i === 0) first_occur = index_content;
index_num++;
}
});
}
// show search results
if (isMatch) {
var str = '';
str += '<div class="tile"><div class="tile-content">';
// highlight keyword in title
var match_title = data.title;
keywords.forEach(function (keyword) {
var regS = new RegExp(keyword, 'gi');
match_title = match_title.replace(regS, '<strong><mark>' + window.searchEscape(keyword) + '</mark></strong>');
})
str += '<a href="' + data.url + '"><p class="tile-title search-result-title">' + match_title + '</p></a>';
str += '<p class="text-gray search-result-summary">';
str += '<span class="saerch-result-date">' + data_date + '</span>';
var content = data.content;
if (first_occur >= 0) {
/* cut out characters & highlight keyword in content
There were still some bugs when cutting CJK.
Need to set max-height and overflow:none to elements contain search result summary
*/
var start = first_occur - 15;
var end = first_occur + 20;
if (start < 0) start = 0;
if (start === 0) end = 20;
if (end > content.length) end = content.length - 20;
var match_content = content.substr(start, end);
keywords.forEach(function (keyword) {
var regS = new RegExp(keyword, 'gi');
match_content = match_content.replace(regS, '<strong><mark>' + window.searchEscape(key) + '</mark></strong>');
})
str += match_content + '...</p>';
}
str += '</div></div>';
resultArray.push([str, data_weight]);
}
});
var resultHTML = (function () {
var html = '';
resultArray.sort(function (x, y) {
return y[1] - x[1];
});
for (var i in resultArray) {
html += resultArray[i][0];
}
return html;
})();
$resultNum.appendChild(document.createTextNode(resultArray.length));
if (index_num <= 0) {
$resultInfo.style.display = 'none';
$resultContent.innerHTML = noResultText;
} else {
$resultInfo.style.display = 'block';
$resultContent.innerHTML = resultHTML;
}
}
// Search only when there is a search query
if (typeof (searchKeyword) !== 'undefined') {
search(searchKeyword);
// Set form value
document.getElementById('search-field').setAttribute('value', searchKeyword);
}
});
};
})();