NB: This is just a place to share code. You might have to adjust it to suit the XML file generated by your static site generator. Please do reach out via email if you want to learn more.
Step 1: Create a JSON file with search entries from XML feed via R.
library(purrr)
library(dplyr)
library(stringr)
XML::xmlParse("./docs/index.xml") %>%
XML::xmlToList() %>%
(function(x) x$channel) %>% # get entries
(function(x) x[lapply(x, length)>4]) %>% # get true entries
map(., as.data.frame) %>% # cast to df
do.call(rbind, .) -> d
# Clean entries
d <- d %>%
filter(title!="Flying DVD (JS)") %>%
mutate_if(is.character, function(x) sapply(x, utils::URLdecode)) %>% # %20 etc
mutate_if(is.character, function(x) textclean::replace_html(x)) %>% # & etc
mutate_if(is.character, function(x) str_replace_all(x, "\n", " ")) %>% # verbatim \n
mutate_if(is.character, function(x) base::trimws(x)) %>% # redundant whitespace
mutate_if(is.character, function(x) str_squish(x)) %>% # redundant whitespace
mutate_if(is.character, function(x) str_remove_all(x, "[\"\'{}]")) %>% # parse correctly
mutate_if(is.character, function(x) str_remove_all(x, "[\r\n]")) # line breaks
# Sample Entry
#title: "Reactive Word and Character Counter",
#url: "/project/js_wc/",
#date: "",
#content: "word character counter count char text length",
#summary: "Word Count: 0"
# cat()
cat_entry <- function(d, i) {
cat('title: \"', d$title[i], '\",\n', sep="")
cat('url: \"', d$link[i], '\",\n', sep="")
cat('date: \"\",\n', sep="") # I personally find the dates unnecessary
cat('content: \"', d$description[i], '\",\n', sep="") # search tokens
cat('summary: \"', d$description[i] %>% str_trunc(500), '\"\n', sep="") # visible
}
sink("./themes/min_night/layouts/partials/search_bar_entries.html")
cat("<script>\n\nvar searchIndex = [")
for (i in 1:nrow(d)){
cat("{\n")
cat_entry(d, i)
if (i!=nrow(d)) cat("},\n") else cat("}\n") # last entry
}
cat("];;\n</script>")
sink()
Step 2: Use an open source script and embed it in a Hugo shortcode together with the content created above.
<h3>Search this Website</h3>
<form
action="https://www.google.com/search?q=site%3cborchers.com&oq=site%3cborchers.com" id="form-search">
<label class="screen-reader" for="input-search"></label>
<input type="text" name="q" class="input-search input-inline
no-margin-bottom" id="input-search" placeholder="Search for..."><button type="submit" class="btn-search" id="submit-search">
<svg xmlns="http://www.w3.org/2000/svg" style="height: 1em; width: 1em;" viewBox="0 0 32 32" aria-labelledby="search-title"><title id="search-title">Search</title><path fill="currentColor" d="M31.008 27.23l-7.58-6.446c-.784-.705-1.622-1.03-2.3-.998C22.92 17.69 24 14.97 24 12 24 5.37 18.627 0 12 0S0 5.37 0 12c0 6.626 5.374 12 12 12 2.973 0 5.692-1.082 7.788-2.87-.03.676.293 1.514.998 2.298l6.447 7.58c1.105 1.226 2.908 1.33 4.008.23s.997-2.903-.23-4.007zM12 20c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8z"></path></svg>
</button>
</form>
<div id="search-results" aria-live="polite"></div>
</article>
{{ partial "search_bar_entries" . }}
</div>
</main>
<script>
/*! gmt v2.0.0 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/go-make-things | Credits: https://github.com/toddmotto/fluidvids */
!function(){"use strict";Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector);document.querySelectorAll(".edd-buy-now-button").length>0&&document.addEventListener("click",(function(e){e.target.classList.contains("edd-buy-now-button")&&(0!==e.button||e.metaKey||e.ctrlKey||(e.target.innerHTML="Adding to cart...",e.target.classList.add("disabled")))}),!1);var e={selector:["iframe"],players:["www.youtube.com","player.vimeo.com"]},t=[".fluidvids {","width: 100%; max-width: 100%; position: relative;","}",".fluidvids-item {","position: absolute; top: 0px; left: 0px; width: 100%; height: 100%;","}"].join(""),n=document.head||document.getElementsByTagName("head")[0],a=function(t){if(n=t.src,new RegExp("^(https?:)?//(?:"+e.players.join("|")+").*$","i").test(n)&&!t.getAttribute("data-fluidvids")){var n,a,i,s=document.createElement("div");t.parentNode.insertBefore(s,t),t.className+=(t.className?" ":"")+"fluidvids-item",t.setAttribute("data-fluidvids","loaded"),s.className+="fluidvids",s.style.paddingTop=(a=t.height,i=t.width,parseInt(a,10)/parseInt(i,10)*100+"%"),s.appendChild(t)}};e.render=function(){for(var t=document.querySelectorAll(e.selector.join()),n=t.length;n--;)a(t[n])},e.init=function(a){for(var i in a)e[i]=a[i];var s;e.render(),(s=document.createElement("div")).innerHTML="<p>x</p><style>"+t+"</style>",n.appendChild(s.childNodes[1])};e.init({selector:["iframe","object"],players:["www.youtube.com","player.vimeo.com","www.slideshare.net","www.hulu.com","videopress.com/embed/","noti.st"]}),document.querySelector("#mailchimp-form")&&function(e){var t=document.querySelector("#mailchimp-form");if(t){var n=t.querySelector("#mailchimp-email");if(n){var a=t.querySelector("#mc-status"),i=t.querySelector("[data-processing]"),s="Please provide an email address.",o="Please use a valid email address.",r="Success! Thanks for inviting me to your inbox.",c=function(e,t){a&&(a.textContent=e,t?(a.className="success-message",n.className=""):(a.className="error-message",n.className="error"))},x=function(){var n,a;t.setAttribute("data-submitting",!0),n=function(e){for(var t=[],n=0;n<e.elements.length;n++){var a=e.elements[n];a.name&&!a.disabled&&"file"!==a.type&&"reset"!==a.type&&"submit"!==a.type&&"button"!==a.type&&("checkbox"!==a.type&&"radio"!==a.type||a.checked)&&t.push(encodeURIComponent(a.name)+"="+encodeURIComponent(a.value))}return t.join("&")}(t),(a=new XMLHttpRequest).onreadystatechange=function(){if(4===a.readyState){var n=200===a.status,i=JSON.parse(a.responseText);c(n?r:i.message,n),t.removeAttribute("data-submitting"),e&&"function"==typeof e&&e(i)}},a.open("POST","https://gomakethings.com/checkout/wp-json/gmt-mailchimp/v1/subscribe?"+n),a.send()},d=function(){return n.value.length<1?(c(s),!1):!!/^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*(\.\w{2,})+$/.test(n.value)||(c(o),!1)};a&&a.setAttribute("role","status"),t.addEventListener("submit",(function(e){(e.preventDefault(),t.hasAttribute("data-submitting"))||(a&&c(i.getAttribute("data-processing"),!0),d()&&x())}),!1)}}}((function(e){200===e.code&&(window.location.href="https://gomakethings.com/newsletter-success")})),document.body.matches(".type-articles.page-single, .type-notes.page-single, [data-heading-links]")&&function(e,t,n){if(e){var a=document.querySelectorAll(e);t=t||"#",n=n||"anchor-link";for(var i=0;i<a.length;i++)a[i].id&&(a[i].innerHTML+=' <a class="'+n+'" href="#'+a[i].id+'">'+t+"</a>")}}("h2, h3, h4, h5, h6","#","link-no-underline")}();
/*! gmt v2.0.0 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/go-make-things | Credits: https://github.com/toddmotto/fluidvids */
!function(){"use strict";var e,t,n,i,r;e=function(e,t){return'<div class="margin-bottom" id="search-result-'+t+'"><aside class="text-muted text-small"><time datetime="'+e.datetime+'" pubdate>'+e.date+'</time></aside><h2 class="h3 link-block-styled link-no-underline no-padding-top no-margin-bottom"><a class="link-no-underline" href="'+e.url+'">'+e.title+"</a></h2>"+e.summary.slice(0,150)+"...</div>"},t=document.querySelector("#form-search"),n=document.querySelector("#input-search"),i=document.querySelector("#search-results"),r=function(t){var n=t.split(" ").map((function(e){return new RegExp(e,"gi")})),r=searchIndex.reduce((function(e,t,i){var r=0;return n.forEach((function(e){e.test(t.title)&&(r+=20),e.test(t.content)&&(r+=1)})),r>0&&e.push({priority:r,article:t}),e}),[]).sort((function(e,t){return t.priority-e.priority}));i.innerHTML=r.length<1?"<p>Sorry, no matches were found.</p>":function(t){var n="<p>Found "+t.length+" matching pages</p>";return n+=t.map((function(t,n){return e(t.article,n)})).join("")}(r),function(e){history.pushState&&history.pushState({},document.title,window.location.origin+window.location.pathname+"?s="+encodeURI(e))}(t)},e&&"function"==typeof e&&t&&n&&i&&searchIndex&&(n.value=n.value.replace(" site:"+window.location.host,""),t.addEventListener("submit",(function(e){e.preventDefault(),r(n.value)}),!1),function(){var e,t,i,o,a=(e="s",i=t||window.location.href,(o=new RegExp("[?&]"+e+"=([^&#]*)","i").exec(i))?o[1]:null);if(a){var c=decodeURI(a);n.value=c,r(c)}}())}();
/*! gmt v2.0.0 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/go-make-things | Credits: https://github.com/toddmotto/fluidvids */
!function(){"use strict";navigator&&navigator.serviceWorker&&navigator.serviceWorker.register("/sw.js"),navigator.serviceWorker.controller&&window.addEventListener("load",(function(){navigator.serviceWorker.controller.postMessage("cleanUp")}))}();
</script>