hydesearch
Version:
Experimental Frontend Search Engine for Hyde Documentation Sites
202 lines (198 loc) • 7.59 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>HydeSearch Demo</title>
<style>
/* Demo Page Styles */
body {
background-color: #f2f2f2;
font-family: 'Raleway', sans-serif;
font-size: 16px;
line-height: 1.5;
color: #333;
padding: 24px 16px;
display: flex;
flex-direction: column;
}
header {
margin-top: 0;
margin-bottom: 20px;
}
h1 {
font-size: 1.6em;
margin-top: 4px;
margin-bottom: 8px;
line-height: 1.2;
}
main {
max-width: 600px;
overflow: auto;
background: white;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
@media screen and (min-width: 800px) {
body {
flex-direction: row;
justify-content: space-evenly;
}
main, aside {
width: 45%;
padding-left: 16px;
padding-right: 16px;
height: fit-content;
}
main {
max-width: 600px;
margin-top: 16px;
}
aside {
width: 40%;
max-width: 65ch;
}
}
@media screen and (min-width: 1200px) {
body {
padding-left: 8vw;
padding-right: 8vw;
}
}
input {
font-size: 16px;
line-height: 1.5;
padding: 4px 8px;
}
label {
font-size: 14px;
font-weight: bold;
display: block;
margin-bottom: 8px;
}
</style>
<style>
/* Sample Styles */
.hyde-search-context {
margin-bottom: 8px;
white-space: pre-line;
}
.search-term-count {
font-size: 0.9em;
font-style: italic;
color: #555;
}
.search-status small {
opacity: 0.75;
}
</style>
<noscript>
<style>#hyde-search form {display: none;}</style>
</noscript>
</head>
<body>
<main>
<header>
<strong role="doc-subtitle" style="font-size: 1.2em;">#CodingInPublic</strong>
<h1>Experimental Frontend Search Engine for Hyde Documentation Sites</h1>
<p role="doc-subtitle" style="margin-top: 0; margin-bottom: 0;">
<strong>Fully client-side search using a precompiled JSON search index.</strong>
</p>
<p role="doc-introduction" style="margin-top: 4px;">
Written in object-oriented TypeScript. Compiled to plain JavaScript. Zero dependencies.
<span title="Network resource size">~1.7kB</span>.
</p>
</header>
<div id="hyde-search">
<noscript>
The search feature requires JavaScript to be enabled in your browser.
</noscript>
<label for="search-input">Try searching! 👇</label>
<input type="search" name="search" id="search-input" placeholder="Search..." autocomplete="off" autofocus>
</div>
</main>
<aside>
<header>
<h2>About</h2>
<p>
This plugin for the HydePHP static site generator was created
as a TypeScript learning project, and turned out to be much
more useful than initially expected.
</p>
</header>
<article>
<h3>Links and information</h3>
<ul>
<li>
Try the search on the <a href="https://demos.desilva.se/gist/github/hydephp/experiments/hydesearch/">hosted live demo</a>
</li>
<li>
Find the <a href="https://github.com/hydephp/HydeSearch">source code on GitHub</a>
</li>
<li>
Learn more about Hyde at <a href="https://hydephp.com/">HydePHP.com</a>
</li>
</ul>
</article>
<article>
<h3>How does it work?</h3>
<h4>
This search engine is designed to be an addon to HydePHP documentation sites.
</h4>
<p>
It works by using a precompiled JSON search index that contains the searchable content
for all the pages, as well as a link to them. The current version assumes that the
searchable content is the entire page content, but it could just as well be a string
of keywords, excerpts, or something else.
</p>
<h4>
Here's a walk-through of the process:
</h4>
<ol>
<li>During the Hyde build process, a JSON search index is generated.</li>
<li>This search index is loaded by the HydeSearch script using AJAX.</li>
<li>When typing in the search field, the results are filtered in realtime,
and then sorted by the number of matches.</li>
</ol>
<p>
For the context section for each result, HydeSearch finds the first
occurrence of the search term in the page content, extracts the
whole sentence, and highlights the matching word.
</p>
<h4>
About the dataset
</h4>
<p>
Since I love working with real data, I'm using the entire
Alice's Adventures in Wonderland book as it's in the public domain.
</p>
<p>
Each chapter has been split into a Markdown page file.
The files were then placed in the _docs folder of a Hyde installation to be processed by HydePHP.
</p>
<ul>
<li>It took an average of 1,265.51ms to generate the search index JSON.</li>
<li>Each entry in the index contains the entire chapter in plain text.</li>
<li>The file weights 148kB. When testing in production, only 55.2 kB is sent over the air.</li>
<li>However, since the file is automatically cached by the browser, the load time is only ~2ms on my device.</li>
<li>Since the index is loaded asynchronously, and only once per page, that's good with me.</li>
</ul>
<p>
To conserve space and improve performance on sites with many pages,
alternative strategies could be used instead of loading the whole page.
</p>
</article>
</aside>
<script src="dist/HydeSearch.js" defer></script>
<script>
window.addEventListener('load', function() {
const searchIndexLocation = 'tests/search.json';
const Search = new HydeSearch(searchIndexLocation).withDebugOutput();
Search.init();
});
</script>
</body>
</html>