From 7622913ac25fd6e5ff391b558d57ecc10fb32ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Weber?= Date: Sun, 24 Sep 2023 00:27:39 +0200 Subject: [PATCH] search: add breadcrumb to dedicated search results #647 --- exampleSite/config/_default/config.toml | 1 + .../content/basics/configuration/_index.en.md | 2 + .../content/basics/migration/_index.en.md | 6 ++- layouts/_default/index.json | 9 +++- layouts/_default/index.search.js | 9 +++- layouts/partials/breadcrumbs.html | 54 +++++++++++++++++++ layouts/partials/header.html | 53 +----------------- static/css/auto-complete.css | 7 +++ static/css/ie.css | 7 +++ static/css/theme.css | 12 ++++- static/css/variant.css | 4 ++ static/js/search.js | 34 ++++++++---- 12 files changed, 133 insertions(+), 65 deletions(-) create mode 100644 layouts/partials/breadcrumbs.html diff --git a/exampleSite/config/_default/config.toml b/exampleSite/config/_default/config.toml index ff51da416d..a15c6edcd8 100644 --- a/exampleSite/config/_default/config.toml +++ b/exampleSite/config/_default/config.toml @@ -215,6 +215,7 @@ title = "Hugo Relearn Documentation" showVisitedLinks = true collapsibleMenu = true disableBreadcrumb = false + disableRootBreadcrumb = true disableInlineCopyToClipBoard = true disableNextPrev = false disableLandingPageButton = true diff --git a/exampleSite/content/basics/configuration/_index.en.md b/exampleSite/content/basics/configuration/_index.en.md index d19cbedae5..afe44d5e65 100644 --- a/exampleSite/content/basics/configuration/_index.en.md +++ b/exampleSite/content/basics/configuration/_index.en.md @@ -53,6 +53,8 @@ Note that some of these parameters are explained in details in other sections of disableLanguageSwitchingButton = false # Hide breadcrumbs in the header and only show the current page title disableBreadcrumb = true + # Hide the root (first) breadcrumb in the header + disableRootBreadcrumb = true # If set to true, hide table of contents menu in the header of all pages disableToc = false # If set to false, load the MathJax module on every page regardless if a MathJax shortcode is present diff --git a/exampleSite/content/basics/migration/_index.en.md b/exampleSite/content/basics/migration/_index.en.md index 2a1c3594ce..a38b596779 100644 --- a/exampleSite/content/basics/migration/_index.en.md +++ b/exampleSite/content/basics/migration/_index.en.md @@ -32,7 +32,11 @@ This document shows you what's new in the latest release. For a detailed list of In this case it is advised to remove the `title` from the headless branch parent's frontmatter, as it will otherwise appear in your breadcrumbs. -- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} The above change has a nice side effect. It is now possible to overwrite the setting for `collapsibleMenu` of your `config.toml` inside of a page's frontmatter. +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} It is now possible to overwrite the setting for `collapsibleMenu` of your `config.toml` inside of a page's frontmatter. + +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} It is now possible to remove the root breadcrumb by setting `disableRootBreadcrumb=true` in your `config.toml`. + +- {{% badge style="info" icon="plus-circle" title=" " %}}New{{% /badge %}} The output of the dedicated search page now displays the result's breadcrumb. --- diff --git a/layouts/_default/index.json b/layouts/_default/index.json index f0c5ea4ff2..abd89e5696 100644 --- a/layouts/_default/index.json +++ b/layouts/_default/index.json @@ -15,7 +15,14 @@ {{- end }} {{- $title = printf "%s %s %s" $title (default "::" .Site.Params.titleSeparator) .Title }} {{- end }} - {{- $pages = $pages | append (dict "uri" (partial "relLangPrettyUglyURL.hugo" (dict "to" .)) "title" $title "tags" .Params.tags "description" .Description "content" (.Plain | htmlUnescape)) }} + {{- $pages = $pages | append (dict + "uri" (partial "relLangPrettyUglyURL.hugo" (dict "to" .)) + "title" $title + "tags" .Params.tags + "breadcrumb" (trim ((partial "breadcrumbs.html" (dict "page" . "dirOnly" true)) | plainify | htmlUnescape) "\n\r\t ") + "description" .Description + "content" (.Plain | htmlUnescape) + ) }} {{- end }} {{- end -}} {{- $pages | jsonify (dict "indent" " ") }} diff --git a/layouts/_default/index.search.js b/layouts/_default/index.search.js index 4e98237b5c..aaea2ab9dd 100644 --- a/layouts/_default/index.search.js +++ b/layouts/_default/index.search.js @@ -15,7 +15,14 @@ {{- end }} {{- $title = printf "%s %s %s" $title (default "::" .Site.Params.titleSeparator) .Title }} {{- end }} - {{- $pages = $pages | append (dict "uri" (partial "relLangPrettyUglyURL.hugo" (dict "to" .)) "title" $title "tags" .Params.tags "description" .Description "content" (.Plain | htmlUnescape)) }} + {{- $pages = $pages | append (dict + "uri" (partial "relLangPrettyUglyURL.hugo" (dict "to" .)) + "title" $title + "tags" .Params.tags + "breadcrumb" (trim ((partial "breadcrumbs.html" (dict "page" . "dirOnly" true)) | plainify | htmlUnescape) "\n\r\t ") + "description" .Description + "content" (.Plain | htmlUnescape) + ) }} {{- end }} {{- end -}} var relearn_search_index = {{ $pages | jsonify (dict "indent" " ") }} diff --git a/layouts/partials/breadcrumbs.html b/layouts/partials/breadcrumbs.html new file mode 100644 index 0000000000..a1cb093266 --- /dev/null +++ b/layouts/partials/breadcrumbs.html @@ -0,0 +1,54 @@ +{{- $page := .page }} +{{- $to := $page }} +{{- $pageurl := partial "relLangPrettyUglyURL.hugo" (dict "to" $page) }} +{{- $lasturl := partial "relLangPrettyUglyURL.hugo" (dict "to" $page) }} +{{- if .dirOnly }} + {{- $page = $page.Parent }} + {{- $to = $page }} + {{- $lasturl = partial "relLangPrettyUglyURL.hugo" (dict "to" $page) }} +{{- end }} +{{- $depth := add 1 (int (partial "get-page-depth.hugo" (dict "page" $page))) }} +{{- if .page.Site.Params.disableRootBreadcrumb }} + {{- $depth = add $depth -1 }} +{{- end }} +{{- $breadcrumb := slice }} +{{- range seq $depth }} + {{- if $to }} + {{- if $to.Title }} + {{- $breadcrumb = $breadcrumb | append $to }} + {{- end }} + {{- else }} + {{- break }} + {{- end }} + {{- $to = $to.Parent }} +{{- end }} +{{- $len := len $breadcrumb -}} +{{- $breadcrumbReversed := slice }} +{{- range seq $len }} + {{- $breadcrumbReversed = $breadcrumbReversed | append (index $breadcrumb (sub $len .)) }} +{{- end }} +{{- range $i, $e := $breadcrumbReversed }} + {{- $to := $e }} + {{- $title := $to.Title }} + {{- if eq .Kind "taxonomy" }} + {{- $title = i18n $to.Data.Plural }} + {{- if not $title }} + {{- $title = $to.Data.Plural }} + {{- end }} + {{- else if eq .Kind "term" }} + {{- $title = i18n $to.Data.Singular }} + {{- if not $title }} + {{- $title = $to.Data.Singular }} + {{- end }} + {{- $title = printf "%s %s %s" $title (default "::" .Site.Params.titleSeparator) $to.Title }} + {{- end }} + {{- if not $title }} + {{- $title = $to.Site.Title }} + {{- end }} + {{- $url := partial "relLangPrettyUglyURL.hugo" (dict "to" $to) }} + {{- $isPage := eq $url $pageurl }} + {{- $isLast := eq $url $lasturl }} + {{- $link := and $url (not $isPage) }} + {{- printf "{{ if $link }}{{end}}{{ $title }}{{ if $link }}{{ end }}{{ if not $isLast }}{{ (printf " %s " (default ">" .Site.Params.breadcrumbSeparator)) | safeHTML }}{{ end }} +{{- end }} \ No newline at end of file diff --git a/layouts/partials/header.html b/layouts/partials/header.html index 73d11b0064..933de0fef9 100644 --- a/layouts/partials/header.html +++ b/layouts/partials/header.html @@ -77,7 +77,7 @@ {{- $showBreadcrumb := (and (not .Params.disableBreadcrumb) (not .Site.Params.disableBreadcrumb)) }} {{- if $showBreadcrumb }} {{- else }} @@ -92,53 +92,4 @@ {{- $hook := "styleclass" }}
-
-{{- define "breadcrumb" }} - {{- $breadcrumb := slice }} - {{- $page := .page }} - {{- $pageurl := partial "relLangPrettyUglyURL.hugo" (dict "to" $page) }} - {{- $to := .to }} - {{- $breadcrumb = $breadcrumb | append $to }} - {{- $depth := int (partial "get-page-depth.hugo" (dict "page" $page)) }} - {{- range seq $depth }} - {{- $to = $to.Parent }} - {{- if $to }} - {{- if $to.Title }} - {{- $breadcrumb = $breadcrumb | append $to }} - {{- end }} - {{- else }} - {{- break }} - {{- end }} - {{- end }} - {{- $len := len $breadcrumb -}} - {{- $breadcrumbReversed := slice }} - {{- range seq $len }} - {{- $breadcrumbReversed = $breadcrumbReversed | append (index $breadcrumb (sub $len .)) }} - {{- end }} - {{- $depth := 0 }} - {{- range $i, $e := $breadcrumbReversed }} - {{- $to := $e }} - {{- $depth = add $depth 1 }} - {{- $title := $to.Title }} - {{- if eq .Kind "taxonomy" }} - {{- $title = i18n $to.Data.Plural }} - {{- if not $title }} - {{- $title = $to.Data.Plural }} - {{- end }} - {{- else if eq .Kind "term" }} - {{- $title = i18n $to.Data.Singular }} - {{- if not $title }} - {{- $title = $to.Data.Singular }} - {{- end }} - {{- $title = printf "%s %s %s" $title (default "::" .Site.Params.titleSeparator) $to.Title }} - {{- end }} - {{- if not $title }} - {{- $title = $to.Site.Title }} - {{- end }} - {{- $url := partial "relLangPrettyUglyURL.hugo" (dict "to" $to) }} - {{- $last := eq $url $pageurl }} - {{- $link := and $url (not $last) }} - {{- printf "{{ if $link }}{{end}}{{ $title }}{{ if $link }}{{ end }}{{ if not $last }}{{ (printf " %s " (default ">" .Site.Params.breadcrumbSeparator)) | safeHTML }}{{ end }} - {{- end }} -{{- end }} \ No newline at end of file +
\ No newline at end of file diff --git a/static/css/auto-complete.css b/static/css/auto-complete.css index 7f4c4df1f5..337547aab9 100644 --- a/static/css/auto-complete.css +++ b/static/css/auto-complete.css @@ -51,6 +51,13 @@ color: rgba( 255, 255, 255, 1 ); } +.autocomplete-suggestion > .breadcrumbs { + font-size: .7869em; + margin-inline-start: 1em; + overflow: hidden; + text-overflow: ellipsis; +} + .autocomplete-suggestion > .context { font-size: .7869em; margin-inline-start: 1em; diff --git a/static/css/ie.css b/static/css/ie.css index 1ed0c56fe7..14a1167cb8 100644 --- a/static/css/ie.css +++ b/static/css/ie.css @@ -177,6 +177,9 @@ .autocomplete-suggestions { text-align: left; } + .autocomplete-suggestion > .breadcrumbs { + margin-left: 1em; + } .autocomplete-suggestion > .context { margin-left: 1em; } @@ -520,6 +523,10 @@ color: rgba( 16, 16, 16, 1 ); /* var(--MAIN-TEXT-color) - inherit is not processed correctly in Chrome */ } + #R-searchresults .autocomplete-suggestion > .breadcrumbs { + color: rgba( 125, 201, 3, 1 ); /* var(--PRIMARY-color) */ + } + .copy-to-clipboard-button { background-color: rgba( 255, 250, 233, 1 ); /* var(--CODE-INLINE-BG-color) */ border-color: rgba( 248, 232, 200, 1 ); /* var(--CODE-INLINE-BORDER-color) */ diff --git a/static/css/theme.css b/static/css/theme.css index fc2b6a818c..0ad455d5e5 100644 --- a/static/css/theme.css +++ b/static/css/theme.css @@ -1742,10 +1742,20 @@ input[type="search"]::-webkit-search-results-decoration { display: none; } height: 0; } +#R-searchresults .autocomplete-suggestion > .breadcrumbs { + font-size: .9rem; + font-weight: 400; + margin-top: .167em; + padding-left: .2em; + padding-right: .2em; +} + #R-searchresults .autocomplete-suggestion > .context { font-size: 1rem; font-weight: 300; - margin-top: .66rem; + margin-top: .66em; + padding-left: .1em; + padding-right: .1em; } .badge { diff --git a/static/css/variant.css b/static/css/variant.css index 5236e34e74..41a36f1ea4 100644 --- a/static/css/variant.css +++ b/static/css/variant.css @@ -262,6 +262,10 @@ table { color: var(--INTERNAL-MAIN-TEXT-color); } +#R-searchresults .autocomplete-suggestion > .breadcrumbs { + color: var(--INTERNAL-PRIMARY-color); +} + .copy-to-clipboard-button { background-color: var(--INTERNAL-CODE-INLINE-BG-color); border-color: var(--INTERNAL-CODE-INLINE-BORDER-color); diff --git a/static/js/search.js b/static/js/search.js index a8d4af118c..68718bad79 100644 --- a/static/js/search.js +++ b/static/js/search.js @@ -213,17 +213,26 @@ function searchDetail( value ) { item.matches.map( function(match){return match.replace(/\W/g, '\\$&')} ).join('|') + ')\\b\\S*(?: +\\S+){0,' + numContextWords + '}'; var context = page.content.match(new RegExp(contextPattern, 'i')); - var divcontext = document.createElement('div'); - divcontext.className = 'context'; - divcontext.innerText = (context || ''); var divsuggestion = document.createElement('a'); divsuggestion.className = 'autocomplete-suggestion'; divsuggestion.setAttribute('data-term', value); divsuggestion.setAttribute('data-title', page.title); divsuggestion.setAttribute('href', baseUri + page.uri); divsuggestion.setAttribute('data-context', context); - divsuggestion.innerText = '» ' + page.title; - divsuggestion.appendChild(divcontext); + var divtitle = document.createElement('div'); + divtitle.className = 'title'; + divtitle.innerText = '» ' + page.title; + divsuggestion.appendChild( divtitle ); + var divbreadcrumb = document.createElement('div'); + divbreadcrumb.className = 'breadcrumbs'; + divbreadcrumb.innerText = (page.breadcrumb || ''); + divsuggestion.appendChild( divbreadcrumb ); + if( context ){ + var divcontext = document.createElement('div'); + divcontext.className = 'context'; + divcontext.innerText = (context || ''); + divsuggestion.appendChild( divcontext ); + } results.appendChild( divsuggestion ); }); window.relearn.markSearch(); @@ -276,17 +285,22 @@ function startSearch(){ item.matches.map( function(match){return match.replace(/\W/g, '\\$&')} ).join('|') + ')\\b\\S*(?: +\\S+){0,' + numContextWords + '}'; var context = page.content.match(new RegExp(contextPattern, 'i')); - var divcontext = document.createElement('div'); - divcontext.className = 'context'; - divcontext.innerText = (context || ''); var divsuggestion = document.createElement('div'); divsuggestion.className = 'autocomplete-suggestion'; divsuggestion.setAttribute('data-term', term); divsuggestion.setAttribute('data-title', page.title); divsuggestion.setAttribute('data-uri', baseUri + page.uri); divsuggestion.setAttribute('data-context', context); - divsuggestion.innerText = '» ' + page.title; - divsuggestion.appendChild(divcontext); + var divtitle = document.createElement('div'); + divtitle.className = 'title'; + divtitle.innerText = '» ' + page.title; + divsuggestion.appendChild( divtitle ); + if( context ){ + var divcontext = document.createElement('div'); + divcontext.className = 'context'; + divcontext.innerText = (context || ''); + divsuggestion.appendChild( divcontext ); + } return divsuggestion.outerHTML; }, /* onSelect callback fires when a search suggestion is chosen */