1// A local search script with the help of 2// [hexo-generator-search](https://github.com/PaicHyperionDev/hexo-generator-search) 3// Copyright (C) 2015 4// Joseph Pan <http://github.com/wzpan> 5// Shuhao Mao <http://github.com/maoshuhao> 6// This library is free software; you can redistribute it and/or modify 7// it under the terms of the GNU Lesser General Public License as 8// published by the Free Software Foundation; either version 2.1 of the 9// License, or (at your option) any later version. 10// 11// This library is distributed in the hope that it will be useful, but 12// WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14// Lesser General Public License for more details. 15// 16// You should have received a copy of the GNU Lesser General Public 17// License along with this library; if not, write to the Free Software 18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19// 02110-1301 USA 20// 21// Modified by: 22// Pieter Robberechts <http://github.com/probberechts> 23 24/*exported searchFunc*/ 25var searchFunc = function(path, searchId, contentId) { 26 27 function stripHtml(html) { 28 html = html.replace(/<style([\s\S]*?)<\/style>/gi, ''); 29 html = html.replace(/<script([\s\S]*?)<\/script>/gi, ''); 30 html = html.replace(/<figure([\s\S]*?)<\/figure>/gi, ''); 31 html = html.replace(/<\/div>/ig, '\n'); 32 html = html.replace(/<\/li>/ig, '\n'); 33 html = html.replace(/<li>/ig, ' * '); 34 html = html.replace(/<\/ul>/ig, '\n'); 35 html = html.replace(/<\/p>/ig, '\n'); 36 html = html.replace(/<br\s*[\/]?>/gi, "\n"); 37 html = html.replace(/<[^>]+>/ig, ''); 38 return html; 39 } 40 41 function getAllCombinations(keywords) { 42 var i, j, result = []; 43 44 for (i = 0; i < keywords.length; i++) { 45 for (j = i + 1; j < keywords.length + 1; j++) { 46 result.push(keywords.slice(i, j).join(' ')); 47 } 48 } 49 return result; 50 } 51 52 $.ajax({ 53 url: path, 54 dataType: "xml", 55 success: function(xmlResponse) { 56 // get the contents from search data 57 var datas = $("entry", xmlResponse).map(function() { 58 return { 59 title: $("title", this).text(), 60 content: $("content", this).text(), 61 url: $("link", this).attr('href') 62 }; 63 }).get(); 64 65 var $input = document.getElementById(searchId); 66 if (!$input) { return; } 67 var $resultContent = document.getElementById(contentId); 68 69 $input.addEventListener("input", function(){ 70 var resultList = []; 71 var keywords = getAllCombinations(this.value.trim().toLowerCase().split(' ')) 72 .sort(function(a,b) { return b.split(' ').length - a.split(' ').length; }); 73 $resultContent.innerHTML = ""; 74 if (this.value.trim().length <= 0) { 75 return; 76 } 77 // perform local searching 78 datas.forEach(function(data) { 79 var matches = 0; 80 if (!data.title || data.title.trim() === "") { 81 data.title = "Untitled"; 82 } 83 var dataTitle = data.title.trim().toLowerCase(); 84 var dataContent = stripHtml(data.content.trim()); 85 var dataUrl = data.url; 86 var indexTitle = -1; 87 var indexContent = -1; 88 var firstOccur = -1; 89 // only match artiles with not empty contents 90 if (dataContent !== "") { 91 keywords.forEach(function(keyword, i) { 92 indexTitle = dataTitle.indexOf(keyword); 93 indexContent = dataContent.indexOf(keyword); 94 95 if( indexTitle >= 0 || indexContent >= 0 ){ 96 matches += 1; 97 if (indexContent < 0) { 98 indexContent = 0; 99 } 100 if (firstOccur < 0) { 101 firstOccur = indexContent; 102 } 103 } 104 }); 105 } 106 // show search results 107 if (matches > 0) { 108 var searchResult = {}; 109 searchResult.rank = matches; 110 searchResult.str = "<li><a href='"+ dataUrl +"' class='search-result-title'>"+ dataTitle +"</a>"; 111 if (firstOccur >= 0) { 112 // cut out 100 characters 113 var start = firstOccur - 20; 114 var end = firstOccur + 80; 115 116 if(start < 0){ 117 start = 0; 118 } 119 120 if(start == 0){ 121 end = 100; 122 } 123 124 if(end > dataContent.length){ 125 end = dataContent.length; 126 } 127 128 var matchContent = dataContent.substr(start, end); 129 130 // highlight all keywords 131 var regS = new RegExp(keywords.join('|'), "gi"); 132 matchContent = matchContent.replace(regS, function(keyword) { 133 return "<em class=\"search-keyword\">"+keyword+"</em>"; 134 }); 135 136 searchResult.str += "<p class=\"search-result\">" + matchContent +"...</p>"; 137 } 138 searchResult.str += "</li>"; 139 resultList.push(searchResult) 140 } 141 }); 142 resultList.sort(function(a, b) { 143 return b.rank - a.rank; 144 }) 145 var result ="<ul class=\"search-result-list\">"; 146 for (var i = 0; i < resultList.length; i++) { 147 result += resultList[i].str; 148 } 149 result += "</ul>"; 150 $resultContent.innerHTML = result; 151 }); 152 } 153 }); 154};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.