// // Search engine of the "search" page (ES module). // // The search index and the taxonomies are generated by Hugo as a separate // JSON file (see layouts/search.searchindex.json), loaded when the page is // displayed and cached by the browser. The URL of the index and the translated // strings are embedded in the page in a JSON data block, so that no inline // script is needed (Content Security Policy). // import Fuse from './fuse.basic.min.js'; var searchConfig = JSON.parse(document.getElementById('search-config').textContent); var taxonomies = {}; var fuse = null; var searchResults = document.getElementById('searchResults'); // targets the
above var searchInput = document.getElementById('searchInput'); // input box for search var lastSearch = ""; // Helper function to create an element with attributes function tag(name, attrs) { var el = document.createElement(name.toString()); !!attrs && Object.keys(attrs).forEach(function(key) { el.setAttribute(key, attrs[key]); }); return el; } function printSearchResult(result) { var section = tag("section"); // // Article headline // var a = tag("a", { href: result.item.permalink }); a.textContent = result.item.title; if (result.item.hasEnFlag) { var uk_flag_svg = document.getElementById("embedded-svg-en"); if (uk_flag_svg != null) { var img = uk_flag_svg.firstChild.cloneNode(true); a.appendChild(img); } } var h4 = tag("h4"); h4.textContent = result.item.type_label + " >> "; h4.appendChild(a); section.appendChild(h4); // // Metadata // if (result.item.type != "page") { var div = tag("div", { 'class': 'post-metadata'}); var span_date = tag("span", { 'class': 'publication-date' }); span_date.textContent = searchConfig.i18n.published_on + " " + result.item.date; div.appendChild(span_date); if (result.item.topics != null) { result.item.topics.forEach(function (v) { var topic_detail = taxonomies.topics[v]; if (topic_detail == null) { return; } var span = tag("span", { 'class': 'topic' }); var link_svg = document.getElementById("embedded-svg-link"); if (link_svg != null) { var img = link_svg.firstChild.cloneNode(true); span.appendChild(img); } var a = tag("a", { href: topic_detail.href }); a.textContent = topic_detail.title; span.appendChild(a); div.appendChild(span); }); } if (result.item.opensource != null) { result.item.opensource.forEach(function (v) { var opensource_detail = taxonomies.opensource[v]; if (opensource_detail == null) { return; } var span = tag("span", { 'class': 'opensource' }); var label_svg = document.getElementById("embedded-svg-label"); if (label_svg != null) { var img = label_svg.firstChild.cloneNode(true); span.appendChild(img); } var a = tag("a", { href: opensource_detail.href }); a.textContent = opensource_detail.title; span.appendChild(a); div.appendChild(span); }); } if (result.item.reading_time != null) { var span = tag("span", { 'class': 'reading-time' }); var schedule_svg = document.getElementById("embedded-svg-schedule"); if (schedule_svg != null) { var img = schedule_svg.firstChild.cloneNode(true); span.appendChild(img); } var readingTime = document.createTextNode(result.item.reading_time); span.appendChild(readingTime); div.appendChild(span); } section.appendChild(div); } var p = tag("p", {}); p.textContent = result.item.summary; var a = tag("a", { href: result.item.permalink, 'class': 'continue-reading' }); a.textContent = searchConfig.i18n.continue_reading; p.appendChild(a); section.appendChild(p); searchResults.appendChild(section); } function clearSearchResults() { var child = searchResults.lastElementChild; while (child) { searchResults.removeChild(child); child = searchResults.lastElementChild; } } // // Fuse.js options; check fuse.js website for details // var fuseOptions = { shouldSort: true, ignoreLocation: true, threshold: 0.4, minMatchCharLength: 3, keys: [ 'title', 'permalink', 'summary', 'topics', 'opensource' ] }; // // Load the search index and initialize Fuse.js // var searchReady = fetch(searchConfig.indexUrl) .then(function (response) { if (!response.ok) { throw new Error("Cannot load the search index: HTTP " + response.status); } return response.json(); }) .then(function (data) { taxonomies = data.taxonomies; fuse = new Fuse(data.index, fuseOptions); }); // // Run a search query (for "term") every time a letter is typed in the // search box // function executeSearch(term) { if (lastSearch == term) { // Don't query Fuse if the search terms have not changed return; } clearSearchResults(); let results = fuse.search(term); results.slice(0, 20).forEach(printSearchResult); lastSearch = term; } searchInput.addEventListener('input', function () { var term = this.value; searchReady.then(function () { // Only display the results of the latest search terms if (searchInput.value === term) { executeSearch(term); } }); });