UNPKG

hydesearch

Version:

Experimental Frontend Search Engine for Hyde Documentation Sites

1 lines 4.81 kB
var __awaiter=this&&this.__awaiter||function(e,a,h,c){return new(h=h||Promise)(function(s,t){function n(e){try{i(c.next(e))}catch(e){t(e)}}function r(e){try{i(c.throw(e))}catch(e){t(e)}}function i(e){var t;e.done?s(e.value):((t=e.value)instanceof h?t:new h(function(e){e(t)})).then(n,r)}i((c=c.apply(e,a||[])).next())})};class HydeSearch{constructor(e){this.debugOutput=!1,this.searchInput=document.getElementById("search-input"),this.hydeSearchContainer=document.getElementById("hyde-search"),this.searchIndexLocation=e}init(){this.debug("Initializing..."),this.loadIndex().then(()=>{this.debugOutput&&console.log(this.searchIndex)}),this.searchInput.addEventListener("input",()=>{this.search()}),this.createSearchResultsContainer(),this.debug("Initialized.")}withDebugOutput(){return this.debugOutput=!0,this}debug(e){this.debugOutput&&console.log("HS/Debug: "+e)}loadIndex(){return __awaiter(this,void 0,void 0,function*(){this.debug("Loading index...");const e=yield fetch(this.searchIndexLocation,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error("Could not load search index from "+this.searchIndexLocation);this.searchIndex=yield e.json(),this.debug("Index loaded.")})}search(){var e=window.performance.now();this.debug("Searching... Got input: "+this.searchInput.value);const t=this.searchInput.value;if(this.searchResultsList.innerHTML="",0===t.length)return this.displayEnterSearchQuery();var s=this.searchIndex.filter(e=>e.title.toLowerCase().includes(t.toLowerCase())||e.content.toLowerCase().includes(t.toLowerCase()));return 0<s.length?this.displayResults(s,e):this.displayNoResults()}displayResults(e,t){this.debug("Found "+e.length+" search results.");var s=e.reduce((e,t)=>e+(t.content.match(new RegExp(this.searchInput.value,"gi"))||[]).length,0),s=(this.setSearchStatusMessage("Found "+s+" result"+(1<e.length?"s":"")+" in "+e.length+" pages."),e.sort((e,t)=>(t.content.match(new RegExp(this.searchInput.value,"gi"))||[]).length-(e.content.match(new RegExp(this.searchInput.value,"gi"))||[]).length),e.forEach(e=>{const t=new ResultItem(e.title,e.content,e.destination,e.slug,this.searchInput.value);this.searchResultsList.appendChild(t.createTitleElement()),this.searchResultsList.appendChild(t.createContextElement())}),Math.round(100*(window.performance.now()-t+Number.EPSILON))/100+"ms");this.debug("Execution time: "+s);const n=this.searchResultsContainer.querySelector("p#search-status");n.innerHTML=n.innerText+` <small>~${s}</small>`}displayEnterSearchQuery(){this.setSearchStatusMessage("")}displayNoResults(){this.debug("No results."),this.setSearchStatusMessage("No results found.")}createSearchResultsContainer(){this.searchResultsContainer=document.createElement("div"),this.searchResultsContainer.id="search-results",this.searchResultsContainer.classList.add("hyde-search-results"),this.hydeSearchContainer.appendChild(this.searchResultsContainer),this.searchResultsList=document.createElement("dl"),this.searchResultsList.id="search-results-list",this.searchResultsContainer.appendChild(this.searchResultsList)}setSearchStatusMessage(e){if(!this.searchResultsContainer.querySelector("p#search-status")){const t=document.createElement("p");t.id="search-status",this.searchResultsContainer.prepend(t)}const t=this.searchResultsContainer.querySelector("p#search-status");t.innerText=e}}class ResultItem{constructor(e,t,s,n,r=null){this.title=e,this.content=t,this.destination=s,this.slug=n,this.currentSearchTerm=r,this.searchTermCount=this.getSearchTermCount()}getSearchTermCount(){return this.currentSearchTerm?this.searchTermCount=(this.content.match(new RegExp(this.currentSearchTerm,"gi"))||[]).length:0}createTitleElement(){const e=document.createElement("dt"),t=(e.classList.add("hyde-search-result"),e.id="search-result-"+this.slug,document.createElement("a")),s=(t.href=this.destination,t.innerText=this.title,e.appendChild(t),e.setAttribute("data-matches",this.searchTermCount.toString()),document.createElement("span"));return s.classList.add("search-term-count"),s.innerText=", "+this.searchTermCount+" occurrence"+(1<this.searchTermCount?"s":"")+" found.",e.appendChild(s),e}createContextElement(){const e=document.createElement("dd");return e.classList.add("hyde-search-context"),e.setAttribute("data-for","search-result-"+this.slug),this.highlight(e),e}highlight(e){var t=this.content.indexOf(this.currentSearchTerm),s=this.content.lastIndexOf(".",t),t=this.content.indexOf(".",t);const n=this.content.substring(s+1,t+1);const r=function(){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"};return n.replace(/[&<>"'/]/gi,e=>t[e]).replace(/<\/?[^>]+(>|$)/g,"").trim()}();e.innerHTML=r.replace(new RegExp(this.currentSearchTerm,"gi"),`<mark class="search-highlight">${this.currentSearchTerm}</mark>`)}}