diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 67f73e1..6c2df2c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,12 +9,15 @@ jobs: matrix: hugo-version: - 'latest' - - '0.68.0' + - '0.134.2' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + submodules: true # Fetch Hugo themes (true OR recursive) + fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Setup Hugo - uses: peaceiris/actions-hugo@v2 + uses: peaceiris/actions-hugo@v3 with: hugo-version: ${{ matrix.hugo-version }} extended: true @@ -22,3 +25,10 @@ jobs: - name: Run Hugo working-directory: exampleSite run: hugo --themesDir ../.. + + # - name: Deploy + # uses: peaceiris/actions-gh-pages@v3 + # with: + # github_token: ${{ secrets.GITHUB_TOKEN }} + # publish_dir: ./public + diff --git a/.gitignore b/.gitignore index e52eb52..5944200 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ public/ exampleSite/public/ .DS_Store +.hugo_build.lock diff --git a/README.md b/README.md index bc7f965..fa0c304 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Hugo Book Theme -[](https://gohugo.io) +[](https://gohugo.io) [](LICENSE)  ### [Hugo](https://gohugo.io) documentation theme as simple as plain book - + - [Features](#features) - [Requirements](#requirements) @@ -33,21 +33,46 @@ ## Requirements -- Hugo 0.68 or higher -- Hugo extended version, read more [here](https://gohugo.io/news/0.48-relnotes/) +- Hugo 0.134 or higher +- Hugo extended version, [Installation Instructions](https://gohugo.io/installation/) ## Installation +### Install as git submodule Navigate to your hugo project root and run: ``` -git submodule add https://git.soper.xyz/Soper/hugo-book themes/book +git submodule add https://github.com/alex-shpak/hugo-book themes/hugo-book ``` -Then run hugo (or set `theme = "book"`/`theme: book` in configuration file) +Then run hugo (or set `theme = "hugo-book"`/`theme: hugo-book` in configuration file) ``` -hugo server --minify --theme book +hugo server --minify --theme hugo-book +``` + +### Install as hugo module + +You can also add this theme as a Hugo module instead of a git submodule. + +Start with initializing hugo modules, if not done yet: +``` +hugo mod init github.com/repo/path +``` + +Navigate to your hugo project root and add [module] section to your `hugo.toml`: + +```toml +[module] +[[module.imports]] +path = 'github.com/alex-shpak/hugo-book' +``` + +Then, to load/update the theme module and run hugo: + +```sh +hugo mod get -u +hugo server --minify ``` ### Creating site from scratch @@ -57,54 +82,18 @@ Below is an example on how to create a new site from scratch: ```sh hugo new site mydocs; cd mydocs git init -git submodule add https://github.com/alex-shpak/hugo-book themes/book -cp -R themes/book/exampleSite/content . +git submodule add https://github.com/alex-shpak/hugo-book themes/hugo-book +cp -R themes/hugo-book/exampleSite/content.en/* ./content ``` ```sh -hugo server --minify --theme book +hugo server --minify --theme hugo-book ``` ## Menu -### File tree menu (default) - 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 - -You can also use leaf bundle and the content of its `index.md` file as menu. -Given you have the following file structure: - -``` -├── content -│ ├── docs -│ │ ├── page-one.md -│ │ └── page-two.md -│ └── posts -│ ├── post-one.md -│ └── post-two.md -``` - -Create a file `content/menu/index.md` with the content: - -```md -+++ -headless = true -+++ - -- [Book Example]({{< relref "/docs/" >}}) - - [Page One]({{< relref "/docs/page-one" >}}) - - [Page Two]({{< relref "/docs/page-two" >}}) -- [Blog]({{< relref "/posts" >}}) -``` - -And Enable it by setting `BookMenuBundle: /menu` in Site configuration. - -- [Example menu](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/content/menu/index.md) -- [Example config file](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/config.yaml) -- [Leaf bundles](https://gohugo.io/content-management/page-bundles/) +You can set `title` and `weight` in the front matter of pages to adjust the order and titles in the menu, as well as other parameters to hide or alter urls in the menu. You can choose which folder to use for generating menu with `BookSection` configuration parameter. ## Blog @@ -115,8 +104,8 @@ A blog is not the primary usecase of this theme, so it has only minimal features ### Site Configuration -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). +There are a few configuration options that you can add to your `hugo.toml` file. +You can also see the `yaml` example [here](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/hugo.yaml). ```toml # (Optional) Set Google Analytics if you use it to track your website. @@ -152,10 +141,6 @@ disableKinds = ['taxonomy', 'taxonomyTerm'] # /static/logo.png then the path would be 'logo.png' BookLogo = 'logo.png' - # (Optional, default none) Set leaf bundle to render as side menu - # When not specified file structure and weights will be used - BookMenuBundle = '/menu' - # (Optional, default docs) Specify section of content to render as menu # You can also set value to "*" to render all sections to menu BookSection = 'docs' @@ -163,7 +148,7 @@ disableKinds = ['taxonomy', 'taxonomyTerm'] # Set source repository location. # Used for 'Last Modified' and 'Edit this page' links. BookRepo = 'https://github.com/alex-shpak/hugo-book' - + # Specifies commit portion of the link to the page's last modified commit hash for 'doc' page # type. # Required if 'BookRepo' param is set. @@ -215,16 +200,16 @@ You can specify additional params in the front matter of individual pages: # Set type to 'docs' if you want to render page outside of configured section or if you render section other than 'docs' type = 'docs' -# Set page weight to re-arrange items in file-tree menu (if BookMenuBundle not set) +# Set page weight to re-arrange items in file-tree menu. weight = 10 -# (Optional) Set to 'true' to mark page as flat section in file-tree menu (if BookMenuBundle not set) +# (Optional) Set to 'true' to mark page as flat section in file-tree menu. bookFlatSection = false # (Optional) Set to hide nested sections or pages at that level. Works only with file-tree menu mode bookCollapseSection = true -# (Optional) Set true to hide page or section from side menu (if BookMenuBundle not set) +# (Optional) Set true to hide page or section from side menu. bookHidden = false # (Optional) Set 'false' to hide ToC from page @@ -235,13 +220,18 @@ bookComments = true # (Optional) Set to 'false' to exclude page from search index. bookSearchExclude = true + +# (Optional) Set explicit href attribute for this page in a menu. +bookHref = '' ``` ### Partials -There are few empty partials you can override in `layouts/partials/` +There are layout partials available for you to easily override components of the theme in `layouts/partials/`. -| Partial | Placement | +In addition to this, there are several empty partials you can override to easily add/inject code. + +| Empty Partial | Placement | | -------------------------------------------------- | ------------------------------------------- | | `layouts/partials/docs/inject/head.html` | Before closing `
` tag | | `layouts/partials/docs/inject/body.html` | Before closing `` tag | @@ -265,7 +255,7 @@ There are few empty partials you can override in `layouts/partials/` ### Plugins -There are a few features implemented as plugable `scss` styles. Usually these are features that don't make it to the core but can still be useful. +There are a few features implemented as pluggable `scss` styles. Usually these are features that don't make it to the core but can still be useful. | Plugin | Description | | --------------------------------- | ----------------------------------------------------------- | @@ -281,15 +271,21 @@ There are a few hugo templates inserted in `` - [Google Analytics](https://gohugo.io/templates/internal/#google-analytics) - [Open Graph](https://gohugo.io/templates/internal/#open-graph) +To disable Open Graph inclusion you can create your own empty file `\layouts\_internal\opengraph.html`. +In fact almost empty not quite empty because an empty file looks like absent for HUGO. For example: +``` + +``` + ## Shortcodes -- [Buttons](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/buttons/) -- [Columns](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/columns/) -- [Expand](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/expand/) -- [Hints](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/hints/) -- [KaTeX](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/katex/) -- [Mermaid](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/mermaid/) -- [Tabs](https://themes.gohugo.io/theme/hugo-book/docs/shortcodes/tabs/) +- [Buttons](https://hugo-book-demo.netlify.app/docs/shortcodes/buttons/) +- [Columns](https://hugo-book-demo.netlify.app/docs/shortcodes/columns/) +- [Details](https://hugo-book-demo.netlify.app/docs/shortcodes/details/) +- [Hints](https://hugo-book-demo.netlify.app/docs/shortcodes/hints/) +- [KaTeX](https://hugo-book-demo.netlify.app/docs/shortcodes/katex/) +- [Mermaid](https://hugo-book-demo.netlify.app/docs/shortcodes/mermaid/) +- [Tabs](https://hugo-book-demo.netlify.app/docs/shortcodes/tabs/) By default, Goldmark trims unsafe outputs which might prevent some shortcodes from rendering. It is recommended to set `markup.goldmark.renderer.unsafe=true` if you encounter problems. diff --git a/assets/_defaults.scss b/assets/_defaults.scss index 4c86697..96c4d84 100644 --- a/assets/_defaults.scss +++ b/assets/_defaults.scss @@ -16,7 +16,6 @@ $body-font-weight: normal !default; $body-min-width: 20rem !default; $container-max-width: 80rem !default; -$header-height: 3.5rem !default; $menu-width: 16rem !default; $toc-width: 16rem !default; @@ -48,9 +47,9 @@ $hint-colors: ( } @mixin theme-dark { - --gray-100: rgba(255, 255, 255, 0.1); - --gray-200: rgba(255, 255, 255, 0.2); - --gray-500: rgba(255, 255, 255, 0.5); + --gray-100: #494e54; + --gray-200: #5c6165; + --gray-500: #999d9f; --color-link: #84b2ff; --color-visited-link: #b88dff; diff --git a/assets/_fonts.scss b/assets/_fonts.scss index 223534c..0256840 100644 --- a/assets/_fonts.scss +++ b/assets/_fonts.scss @@ -1,43 +1,28 @@ -/* roboto-300italic - latin */ -@font-face { - font-family: 'Roboto'; - font-style: italic; - font-weight: 300; - font-display: swap; - src: local('Roboto Light Italic'), local('Roboto-LightItalic'), - url('fonts/roboto-v19-latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('fonts/roboto-v19-latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ -} -/* roboto-regular - latin */ @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; - font-display: swap; - src: local('Roboto'), local('Roboto-Regular'), - url('fonts/roboto-v19-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('fonts/roboto-v19-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + font-display: fallback; + src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } -/* roboto-700 - latin */ + @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 700; - font-display: swap; - src: local('Roboto Bold'), local('Roboto-Bold'), - url('fonts/roboto-v19-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('fonts/roboto-v19-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + font-display: fallback; + src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } -/* roboto-mono-regular - latin */ @font-face { font-family: 'Roboto Mono'; font-style: normal; font-weight: 400; - font-display: swap; - src: local('Roboto Mono'), local('RobotoMono-Regular'), - url('fonts/roboto-mono-v6-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('fonts/roboto-mono-v6-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + font-display: fallback; + src: url(https://fonts.gstatic.com/s/robotomono/v23/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_ROW4AJi8SJQt.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* UBUNTU; LOADED BY SOPER */ diff --git a/assets/_main.scss b/assets/_main.scss index 883fbda..7b9e1af 100644 --- a/assets/_main.scss +++ b/assets/_main.scss @@ -9,7 +9,7 @@ body { color: var(--body-font-color); background: var(--body-background); - letter-spacing: 0.33px; + // letter-spacing: 0.33px; font-weight: $body-font-weight; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; @@ -69,6 +69,7 @@ ul.pagination { display: flex; justify-content: center; list-style-type: none; + padding-inline-start: 0px; .page-item a { padding: $padding-16; @@ -84,13 +85,19 @@ ul.pagination { filter: var(--icon-filter); } +a .book-icon { + height: 1em; + width: 1em; + margin-inline-end: .5em; +} + .book-brand { margin-top: 0; + margin-bottom: $padding-16; img { height: 1.5em; - width: auto; - vertical-align: middle; + width: 1.5em; margin-inline-end: $padding-8; } } @@ -135,13 +142,20 @@ ul.pagination { } } -.book-section-flat { - margin-bottom: $padding-16 * 2; - - &:not(:first-child) { - margin-top: $padding-16 * 2; +// for RTL support +body[dir="rtl"] .book-menu { + input.toggle + label::after { + content: "◂"; } + input.toggle:checked + label::after { + content: "▾"; + } +} + +.book-section-flat { + margin: $padding-16 * 2 0; + > a, > span, > label { @@ -160,7 +174,17 @@ ul.pagination { } .book-post { - margin-bottom: $padding-16 * 3; + margin-bottom: $padding-16 * 2; + + .book-post-date img { + height: 1em; + width: 1em; + margin-inline-end: .5em; + } + + .book-post-content > :first-child { + margin-top: $padding-16; + } } .book-header { @@ -170,6 +194,17 @@ ul.pagination { label { line-height: 0; } + + h3 { + overflow: hidden; + text-overflow: ellipsis; + margin: 0 $padding-16; + } + + img.book-icon { + height: 1.5em; + width: 1.5em; + } } .book-search { @@ -226,6 +261,7 @@ ul.pagination { img { height: 1em; + width: 1em; } nav > ul > li:first-child { @@ -236,11 +272,6 @@ ul.pagination { .book-footer { padding-top: $padding-16; font-size: $font-size-14; - - img { - height: 1em; - margin-inline-end: $padding-8; - } } .book-comments { @@ -248,60 +279,11 @@ ul.pagination { } .book-languages { - position: relative; - overflow: visible; - - padding: $padding-16; - margin: -$padding-16; + margin-block-end: $padding-16 * 2; ul { - margin: 0; - padding: 0; - list-style: none; - - li { - white-space: nowrap; - cursor: pointer; - } + padding-inline-start: 1.5em; } - - &:hover, - &:focus, - &:focus-within { - .book-languages-list { - display: block; - } - } - - .book-languages-list { - display: none; - - position: absolute; - bottom: 100%; - left: 0; - padding: $padding-8 0; - - background: var(--body-background); - box-shadow: 0 0 $padding-4 rgba(0, 0, 0, 0.1); - - li img { - opacity: 0.25; - } - - li.active img, - li:hover img { - opacity: initial; - } - - a { - color: inherit; - padding: $padding-8 $padding-16; - } - } -} - -.book-home { - padding: $padding-16; } // Responsive styles @@ -324,7 +306,6 @@ ul.pagination { .book-menu { visibility: hidden; margin-inline-start: -$menu-width; - font-size: $font-size-base; z-index: 1; } @@ -374,8 +355,8 @@ ul.pagination { } } - //for RTL support - body[dir="rtl"] #menu-control:checked + main { + // for RTL support + body[dir="rtl"] #menu-control:checked ~ main { .book-menu .book-menu-content { transform: translateX(-$menu-width); } diff --git a/assets/_markdown.scss b/assets/_markdown.scss index e71de43..2a95453 100644 --- a/assets/_markdown.scss +++ b/assets/_markdown.scss @@ -65,9 +65,12 @@ img { max-width: 100%; + height: auto; } code { + direction: ltr; + unicode-bidi: embed; padding: 0 $padding-4; background: var(--gray-200); border-radius: $border-radius; @@ -75,6 +78,8 @@ } pre { + direction: ltr; + unicode-bidi: embed; padding: $padding-16; background: var(--gray-100); border-radius: $border-radius; @@ -86,6 +91,10 @@ } } + p { + word-wrap: break-word; + } + blockquote { margin: $padding-16 0; padding: $padding-8 $padding-16 $padding-8 ($padding-16 - $padding-4); //to keep total left space 16dp @@ -129,6 +138,7 @@ ul, ol { padding-inline-start: $padding-16 * 2; + word-wrap: break-word; } dl { @@ -138,20 +148,31 @@ } dd { - margin-inline-start: $padding-16; + margin-inline-start: 0; margin-bottom: $padding-16; } } // Special case for highlighted code with line numbers - .highlight table tr { - td:nth-child(1) pre { - margin: 0; - padding-inline-end: 0; - } - td:nth-child(2) pre { - margin: 0; - padding-inline-start: 0; + .highlight { + direction: ltr; + unicode-bidi: embed; + border-radius: $border-radius; + overflow: hidden; + + table tr { + td pre code > span { + display: flex; + } + + td:nth-child(1) pre { + margin: 0; + padding-inline-end: 0; + } + td:nth-child(2) pre { + margin: 0; + padding-inline-start: 0; + } } } diff --git a/assets/_shortcodes.scss b/assets/_shortcodes.scss index 714de2a..41a8e3e 100644 --- a/assets/_shortcodes.scss +++ b/assets/_shortcodes.scss @@ -71,7 +71,7 @@ > div { margin: $padding-16 0; - min-width: $body-min-width / 2; + min-width: $body-min-width * 0.66; padding: 0 $padding-16; } } diff --git a/assets/_utils.scss b/assets/_utils.scss index 29ef1ca..92fad0f 100644 --- a/assets/_utils.scss +++ b/assets/_utils.scss @@ -50,6 +50,10 @@ text-align: right; } +.text-small { + font-size: .875em; +} + .hidden { display: none; } diff --git a/assets/clipboard.js b/assets/clipboard.js new file mode 100644 index 0000000..2799f2f --- /dev/null +++ b/assets/clipboard.js @@ -0,0 +1,24 @@ +(function () { + function select(element) { + const selection = window.getSelection(); + + const range = document.createRange(); + range.selectNodeContents(element); + + selection.removeAllRanges(); + selection.addRange(range); + } + + document.querySelectorAll("pre code").forEach(code => { + code.addEventListener("click", function (event) { + if (window.getSelection().toString()) { + return; + } + select(code.parentElement); + + if (navigator.clipboard) { + navigator.clipboard.writeText(code.parentElement.textContent); + } + }); + }); +})(); diff --git a/assets/manifest.json b/assets/manifest.json index 6a137ac..3e0314f 100644 --- a/assets/manifest.json +++ b/assets/manifest.json @@ -1,14 +1,14 @@ { "name": "{{ .Site.Title }}", "short_name": "{{ .Site.Title }}", - "start_url": "{{ "/" | relURL }}", - "scope": "{{ "/" | relURL }}", + "start_url": "{{ "./" | relURL }}", + "scope": "{{ "./" | relURL }}", "display": "standalone", "background_color": "#000000", "theme_color": "#000000", "icons": [ { - "src": "{{ "/favicon.svg" | relURL }}", + "src": "{{ "./favicon.svg" | relURL }}", "sizes": "512x512" } ] diff --git a/assets/menu-reset.js b/assets/menu-reset.js index f3b90c5..37cb47b 100644 --- a/assets/menu-reset.js +++ b/assets/menu-reset.js @@ -1,5 +1,5 @@ (function() { - var menu = document.querySelector("aside.book-menu nav"); + var menu = document.querySelector("aside .book-menu-content"); addEventListener("beforeunload", function(event) { localStorage.setItem("menu.scrollTop", menu.scrollTop); }); diff --git a/assets/plugins/_numbered.scss b/assets/plugins/_numbered.scss index 56cda5a..d7ad4d5 100644 --- a/assets/plugins/_numbered.scss +++ b/assets/plugins/_numbered.scss @@ -1,9 +1,9 @@ $startLevel: 1; $endLevel: 6; -.book-page .markdown { +.book-page .markdown.book-article { @for $currentLevel from $startLevel through $endLevel { - > h#{$currentLevel} { + h#{$currentLevel} { counter-increment: h#{$currentLevel}; counter-reset: h#{$currentLevel + 1}; @@ -19,14 +19,12 @@ $endLevel: 6; } } -.book-toc nav ul { +.book-toc nav#TableOfContents ul { + counter-reset: item; + li { counter-increment: item; - &:first-child { - counter-reset: item; - } - &:before { content: counters(item, ".") ". "; float: left; diff --git a/assets/search-data.js b/assets/search-data.js deleted file mode 100644 index a93664e..0000000 --- a/assets/search-data.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -(function () { - const indexCfg = {{ with i18n "bookSearchConfig" }} - {{ . }}; - {{ else }} - {}; - {{ end }} - - indexCfg.doc = { - id: 'id', - field: ['title', 'content'], - store: ['title', 'href', 'section'], - }; - - const index = FlexSearch.create('balance', indexCfg); - window.bookSearchIndex = index; - - {{- $pages := where .Site.Pages "Kind" "in" (slice "page" "section") -}} - {{- $pages = where $pages "Params.booksearchexclude" "!=" true -}} - {{- $pages = where $pages "Content" "not in" (slice nil "") -}} - - {{ range $index, $page := $pages }} - index.add({ - 'id': {{ $index }}, - 'href': '{{ $page.RelPermalink }}', - 'title': {{ (partial "docs/title" $page) | jsonify }}, - 'section': {{ (partial "docs/title" $page.Parent) | jsonify }}, - 'content': {{ $page.Plain | jsonify }} - }); - {{- end -}} -})(); diff --git a/assets/search-data.json b/assets/search-data.json new file mode 100644 index 0000000..0a65bf0 --- /dev/null +++ b/assets/search-data.json @@ -0,0 +1,17 @@ +[ +{{- $pages := where .Site.Pages "Kind" "in" (slice "page" "section") -}} +{{- $pages = where $pages "Params.bookSearchExclude" "!=" true -}} +{{/* Remove until we know why it does not work, see https://github.com/alex-shpak/hugo-book/issues/528 */}} +{{/*- $pages = where $pages "Content" "not in" (slice nil "") -*/}} +{{- $pages = where $pages "Content" "!=" "" -}} + +{{ range $index, $page := $pages }} +{{ if gt $index 0}},{{end}} { + "id": {{ $index }}, + "href": "{{ $page.RelPermalink }}", + "title": {{ (partial "docs/title" $page) | jsonify }}, + "section": {{ (partial "docs/title" $page.Parent) | jsonify }}, + "content": {{ $page.Plain | jsonify }} +} +{{- end -}} +] diff --git a/assets/search.js b/assets/search.js index 3635a1f..91add6f 100644 --- a/assets/search.js +++ b/assets/search.js @@ -1,9 +1,29 @@ 'use strict'; -{{ $searchDataFile := printf "%s.search-data.js" .Language.Lang }} -{{ $searchData := resources.Get "search-data.js" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify | resources.Fingerprint }} +{{ $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 }}, { + includeScore: true, + useExtendedSearch: true, + fieldNormWeight: 1.5, + threshold: 0.2, + ignoreLocation: true, + keys: [ + { + name: 'title', + weight: 0.7 + }, + { + name: 'content', + weight: 0.3 + } + ] + }); + const input = document.querySelector('#book-search-input'); const results = document.querySelector('#book-search-results'); @@ -20,6 +40,10 @@ * @param {Event} event */ function focusSearchFieldOnKeyPress(event) { + if (event.target.value !== undefined) { + return; + } + if (input === document.activeElement) { return; } @@ -46,11 +70,13 @@ input.removeEventListener('focus', init); // init once input.required = true; - loadScript('{{ "flexsearch.min.js" | relURL }}'); - loadScript('{{ $searchData.RelPermalink }}', function () { - input.required = false; - search(); - }); + fetch(searchDataURL) + .then(pages => pages.json()) + .then(pages => { + window.bookSearchIndex = new Fuse(pages, indexConfig); + }) + .then(() => input.required = false) + .then(search); } function search() { @@ -62,33 +88,19 @@ return; } - const searchHits = window.bookSearchIndex.search(input.value, 10); + const searchHits = window.bookSearchIndex.search(input.value).slice(0,10); searchHits.forEach(function (page) { const li = element('