diff --git a/README.md b/README.md index 25f5278..92e45d2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Hugo Book Theme + [](https://gohugo.io) [](LICENSE)  @@ -94,12 +95,12 @@ hugo server --minify --theme hugo-book ### File tree menu (default) -By default, the theme will render pages from the `content/docs` section as a menu in a tree structure. +By default, the theme will render pages from the `content/docs` section as a menu in a tree structure. You can set `title` and `weight` in the front matter of pages to adjust the order and titles in the menu. ### Leaf bundle menu (Deprecated, to be removed in June 2022) -You can also use leaf bundle and the content of its `index.md` file as menu. +You can also use leaf bundle and the content of its `index.md` file as menu. Given you have the following file structure: ``` @@ -133,14 +134,14 @@ And Enable it by setting `BookMenuBundle: /menu` in Site configuration. ## Blog -A simple blog is supported in the section `posts`. +A simple blog is supported in the section `posts`. A blog is not the primary usecase of this theme, so it has only minimal features. ## Configuration ### Site Configuration -There are a few configuration options that you can add to your `config.toml` file. +There are a few configuration options that you can add to your `config.toml` file. You can also see the `yaml` example [here](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/config.yaml). ```toml @@ -347,7 +348,7 @@ If you want lower maintenance, use one of the released versions. If you want to ### [Extra credits to contributors](https://github.com/alex-shpak/hugo-book/graphs/contributors) -Contributions are welcome and I will review and consider pull requests. +Contributions are welcome and I will review and consider pull requests. Primary goals are: - Keep it simple. diff --git a/assets/_main.scss b/assets/_main.scss index a9ba8ac..c88c78c 100644 --- a/assets/_main.scss +++ b/assets/_main.scss @@ -244,11 +244,65 @@ body[dir="rtl"] .book-menu { } .book-search { + z-index: 2; position: relative; margin: $padding-16 0; border-bottom: 1px solid transparent; + #book-search-input { + display: flex; + align-items: center; + img { + z-index: 5; + position: absolute; + left: 30px; + } + } + #search-overlay { + background-color: #000; + pointer-events: auto; + opacity: 0.1; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + z-index: 3; + } + #book-search-results { + position: absolute; + z-index: 3; + #book-search-hits { + overflow-y: scroll; + max-height: calc(100vh - 130px); // 130px -> uitopbar + content topbar + background-color: var(--body-background); + border-radius: 10px; + box-shadow: 0 16px 32px 16px rgba(0, 0, 0, 0.16); + margin-top: 5px; + padding: 16px; + position: relative; + ul { + margin: 0; + padding: 0; + li { + box-sizing: border-box; + cursor: pointer; + list-style-type: none; + padding: 10px; + h4 { + font-weight: 700; + color: var(--body-font-color); + } + &:hover { + background-color: var(--gray-100); + } + } + } + } + } input { + z-index: 4; + position: relative; width: 100%; padding: 7px 20px 7px 48px; @@ -303,14 +357,6 @@ body[dir="rtl"] .book-menu { } } -#book-search-results { - position: absolute; - z-index: 9999; - background: cyan; - li { - list-style: none; - } -} @media screen and (min-width: $mobile-breakpoint) { .book-search { diff --git a/assets/search.js b/assets/search.js index 2d75fee..2a30cec 100644 --- a/assets/search.js +++ b/assets/search.js @@ -2,29 +2,29 @@ {{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }} {{ $searchData := resources.Get "search-data.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify | resources.Fingerprint }} -{{ $searchConfig := i18n "bookSearchConfig" | default "{}" }} (function () { const searchDataURL = '{{ $searchData.RelPermalink }}'; - const indexConfig = Object.assign({{ $searchConfig }}, { - doc: { - id: 'id', - field: ['title', 'content'], - store: ['title', 'href', 'section'] - } - }); - - const input = document.querySelector('#book-search-input'); - const results = document.querySelector('#book-search-results'); + const input = document.querySelector('#book-search-input input'); + const searchOverlay = document.querySelector('#search-overlay') + const resultsContainer = document.querySelector('#book-search-hits'); + const results = document.querySelector('#book-search-results ul'); + const LIMIT_RESULTS = Infinity + const MIN_INPUT_SIZE = 2 // SDK ✅ + const documents = new Map() if (!input) { return } + // Listeners input.addEventListener('focus', init); input.addEventListener('keyup', search); - document.addEventListener('keypress', focusSearchFieldOnKeyPress); + searchOverlay.addEventListener('click', () => { + hideSearchBox() + }) + /** * @param {Event} event @@ -49,7 +49,7 @@ /** * @param {String} character - * @returns {Boolean} + * @returns {Boolean} */ function isHotkey(character) { const dataHotkeys = input.getAttribute('data-hotkeys') || ''; @@ -59,39 +59,114 @@ function init() { input.removeEventListener('focus', init); // init once input.required = true; - fetch(searchDataURL) .then(pages => pages.json()) .then(pages => { - window.bookSearchIndex = FlexSearch.create('balance', indexConfig); - window.bookSearchIndex.add(pages); + window.lunrIdx = lunr(function() { + this.ref('id') + this.field('id') + this.field('content') + this.field('href') + this.metadataWhitelist = ['position'] + for (const page of pages) { + documents.set(page.id, page) + this.add(page); + } + }) }) .then(() => input.required = false) .then(search); } function search() { + const value = input.value?.trim() + if (input.required) { + return + } + while (results.firstChild) { results.removeChild(results.firstChild); } - if (!input.value) { + if (!value || value.length <= MIN_INPUT_SIZE) { + hideSearchBox() return; } - const searchHits = window.bookSearchIndex.search(input.value, 10); - searchHits.forEach(function (page) { - const li = element('
h&&(l=0),l=l||0,g=l+c,g=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r["char"]]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},e.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})},e.Index.prototype.query=function(t){for(var r=new e.Query(this.fields),i=Object.create(null),n=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u