diff --git a/.gitignore b/.gitignore index 6b89457..7c578ae 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,15 @@ exampleSite/* # Exclude special files in content folder +exampleSite/content/**/ !exampleSite/content -exampleSite/content/* +!exmapleSite/content/about.md !exampleSite/content/archives !exampleSite/content/post +# Exclude special files in data folder +!exampleSite/data + # Exclude special files in static folder !exampleSite/static @@ -15,3 +19,7 @@ exampleSite/content/* !exampleSite/config.yaml !exampleSite/start.sh +data/* +!data/config.yaml +!data/resources.yaml + diff --git a/VERSION b/VERSION index 99eba4d..ef8d756 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.1.0 \ No newline at end of file +4.2.0 \ No newline at end of file diff --git a/assets/css/_common/components/pages/flinks.scss b/assets/css/_common/components/pages/flinks.scss new file mode 100644 index 0000000..5f0ced2 --- /dev/null +++ b/assets/css/_common/components/pages/flinks.scss @@ -0,0 +1,141 @@ +.flinks-block { + + .flinks-block-title { + text-align: center; + font-weight: bold; + } + + .flinks-list-title { + font-size: 1.25em; + font-weight: bold; + } + + .flinks-lists > div:not(:first-child) { + margin-top: 40px; + } + + .flinks-list-desc { + font-style: italic; + } + + .flinks-list-items { + overflow: auto; + padding: 10px 10px 0; + text-align: center; + + + + .flinks-list-item { + @include mobile() { + display: flex; + justify-content: center; + align-items: center; + } + + position: relative; + float: left; + overflow: hidden; + margin: 15px 7px; + width: calc(100% / 3 - 18px); + height: 90px; + border-radius: 8px; + line-height: 17px; + -webkit-transform: translateZ(0); + border: groove 1px var(--highlight-foreground); + box-shadow: .6rem .5rem 0.3rem var(--body-bg-color); + + &:hover:before, + &:focus:before, + &:active:before { + -webkit-transform:scale(1); + -moz-transform:scale(1); + -o-transform:scale(1); + -ms-transform:scale(1); + transform: scale(1); + } + + + &:hover .flinks-item-icon { + margin-left:-10px; + width:0; + } + + &:before { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + background: var(--body-bg-color); + content: ' '; + transition: transform .3s ease-out; + transform: scale(0); + } + + a { + //color: var(--font-color); + text-decoration: none; + } + + .flinks-item-icon { + float: left; + overflow: hidden; + margin: 15px 10px; + width: 60px; + height: 60px; + border-radius: 35px; + border: solid 1px var(--body-bg-color); + -webkit-transition: width .3s ease-out; + -moz-transition: width .3s ease-out; + -o-transition: width .3s ease-out; + -ms-transition: width .3s ease-out; + transition: width .3s ease-out; + + img { + width: 100%; + height: 100%; + -webkit-transition: filter 375ms ease-in .2s,-webkit-transform .3s; + -moz-transition: filter 375ms ease-in .2s,-moz-transform .3s; + -o-transition: filter 375ms ease-in .2s,-o-transform .3s; + -ms-transition: filter 375ms ease-in .2s,-ms-transform .3s; + transition: filter 375ms ease-in .2s,transform .3s; + object-fit: cover; + } + } + + .flinks-item-name, .flinks-item-desc { + overflow:hidden; + -o-text-overflow:ellipsis; + text-overflow:ellipsis; + white-space:nowrap + } + + .flinks-item-name { + padding: 20px 0 0 0; + height: 20px; + font-weight: 700; + font-size: 1em; + font-weight: bold; + + @include mobile() { + display: none; + } + } + + .flinks-item-desc { + padding: 10px 0; + font-size: .92em; + + @include mobile() { + display: none; + } + } + + } + } + + .flinks-page-desc { + margin-top: 20px; + } +} \ No newline at end of file diff --git a/assets/css/_common/components/pages/index.scss b/assets/css/_common/components/pages/index.scss index ee55922..96e1437 100644 --- a/assets/css/_common/components/pages/index.scss +++ b/assets/css/_common/components/pages/index.scss @@ -3,3 +3,4 @@ @import 'schedule'; @import 'breadcrumb'; @import 'tag-cloud'; +@import 'flinks'; \ No newline at end of file diff --git a/assets/css/_common/components/post/index.scss b/assets/css/_common/components/post/index.scss index b8c55d9..0b065ff 100644 --- a/assets/css/_common/components/post/index.scss +++ b/assets/css/_common/components/post/index.scss @@ -18,7 +18,7 @@ .use-motion { @if $motion_trans_post_block { - .post-block, .pagination, .comments, .post-comments { + .post-block, .flinks-block, .pagination, .comments, .post-comments { visibility: hidden; } } diff --git a/assets/css/_common/components/post/post-body.scss b/assets/css/_common/components/post/post-body.scss index 062d816..a7b1caf 100644 --- a/assets/css/_common/components/post/post-body.scss +++ b/assets/css/_common/components/post/post-body.scss @@ -76,4 +76,8 @@ width: 100%; } } + + svg { + max-width: 98%; + } } diff --git a/assets/css/_common/components/post/post-footer.scss b/assets/css/_common/components/post/post-footer.scss index cecdd95..e8c4473 100644 --- a/assets/css/_common/components/post/post-footer.scss +++ b/assets/css/_common/components/post/post-footer.scss @@ -3,7 +3,7 @@ // Fix issue #16 // To do: use `gap` instead of `margin` // See https://caniuse.com/flexbox-gap -.post-footer { +.post-footer, .flinks-list-footer { @include flex-column(); hr{ diff --git a/assets/css/_common/components/third-party/search.scss b/assets/css/_common/components/third-party/search.scss index ca5e9a5..e88eec0 100644 --- a/assets/css/_common/components/third-party/search.scss +++ b/assets/css/_common/components/third-party/search.scss @@ -106,6 +106,13 @@ padding: 5px 0; } } + + mark.search-keyword { + background: transparent; + border-bottom: 1px dashed $red; + color: $red; + font-weight: bold; + } } @if $algolia_search_enable { @@ -169,11 +176,4 @@ margin: auto; } } - - mark.search-keyword { - background: transparent; - border-bottom: 1px dashed $red; - color: $red; - font-weight: bold; - } } diff --git a/assets/css/_common/scaffolding/highlight/copy-code.scss b/assets/css/_common/scaffolding/highlight/copy-code.scss index 63d538c..cdc2f93 100644 --- a/assets/css/_common/scaffolding/highlight/copy-code.scss +++ b/assets/css/_common/scaffolding/highlight/copy-code.scss @@ -2,14 +2,29 @@ .highlight { background: var(--highlight-background); + margin-bottom: 26px; - .table-container, pre { + //TODO Need fixed the copy button show position. + div:first-child { + overflow-x: auto; + } + + pre { position: relative; } - .table-container table tbody tr { - background: none; + table tbody tr { + //TODO Fixed the too long code line over + // layout background color. + background: #272822; } + + /* pre > code span { + white-space: break-spaces; + overflow: hidden; + word-break: break-all; + word-wrap: break-word; + } */ } @if $codeblock_copy_btn_enable { diff --git a/assets/css/_common/scaffolding/highlight/index.scss b/assets/css/_common/scaffolding/highlight/index.scss index 68c6fcc..bea46e8 100644 --- a/assets/css/_common/scaffolding/highlight/index.scss +++ b/assets/css/_common/scaffolding/highlight/index.scss @@ -6,7 +6,7 @@ } pre { - padding: 10px; + padding: 18px; margin: 0; } diff --git a/assets/css/_common/scaffolding/tags/note.scss b/assets/css/_common/scaffolding/tags/note.scss index 877e097..f22fef4 100644 --- a/assets/css/_common/scaffolding/tags/note.scss +++ b/assets/css/_common/scaffolding/tags/note.scss @@ -1,7 +1,7 @@ //@use 'sass:map'; @if $note_style != 'disabled' { - .post-body .note { + .main .note { $note-icons : $note_icons; $note-style : $note_style; diff --git a/assets/css/_schemes/Gemini/index.scss b/assets/css/_schemes/Gemini/index.scss index ad88c56..845e620 100644 --- a/assets/css/_schemes/Gemini/index.scss +++ b/assets/css/_schemes/Gemini/index.scss @@ -25,7 +25,7 @@ // ================================================== // Post blocks. .main-inner > { - .sub-menu, .post-block, .tabs-comment, .comments, .post-comments, .pagination { + .sub-menu, .post-block, .flinks-block, .tabs-comment, .comments, .post-comments, .pagination { background: var(--content-bg-color); border-radius: $border-radius-inner; box-shadow: $box-shadow-inner; @@ -47,7 +47,7 @@ } // Post & Comments blocks. -.post-block, .comments, .post-comments { +.post-block, .flinks-block, .comments, .post-comments { padding: $content-desktop-padding; } @@ -91,7 +91,7 @@ } } - .post-block { + .post-block, .flinks-block { // Inside posts blocks content padding (default 40px). padding: ($content-tablet-padding * 2); } @@ -119,7 +119,7 @@ } } - .post-block { + .post-block, .flinks-block { // Inside posts blocks content padding (default 40px). padding: $sidebar-offset; } diff --git a/assets/js/motion.js b/assets/js/motion.js index b13725d..dfc5a4a 100644 --- a/assets/js/motion.js +++ b/assets/js/motion.js @@ -95,7 +95,7 @@ NexT.motion.middleWares = { }); } - animate(postblock, '.post-block, .pagination, .post-comments'); + animate(postblock, '.post-block,.flinks-block, .pagination, .post-comments'); animate(collheader, '.collection-header'); animate(postheader, '.post-header'); animate(postbody, '.post-body'); diff --git a/assets/js/next-boot.js b/assets/js/next-boot.js index 8f96889..cad11e4 100644 --- a/assets/js/next-boot.js +++ b/assets/js/next-boot.js @@ -4,7 +4,7 @@ NexT.boot = {}; NexT.boot.registerEvents = function() { - // NexT.utils.registerScrollPercent(); + NexT.utils.registerScrollPercent(); // NexT.utils.registerCanIUseTag(); // Mobile top menu bar. diff --git a/assets/js/third-party/search/algolia.js b/assets/js/third-party/search/algolia.js new file mode 100644 index 0000000..dcdb0e7 --- /dev/null +++ b/assets/js/third-party/search/algolia.js @@ -0,0 +1,144 @@ +/* global instantsearch, algoliasearch, CONFIG, pjax */ + +document.addEventListener('DOMContentLoaded', () => { + + const algoiajs = NexT.utils.getCDNResource(NexT.CONFIG.algolia.js); + const instantschjs = NexT.utils.getCDNResource(NexT.CONFIG.algolia.instantjs); + + NexT.utils.getScript(algoiajs, {}); + NexT.utils.getScript(instantschjs, {}).then(() => { + + const { indexname, appid, apikey, hits } = NexT.CONFIG.algolia.cfg; + const indexName = indexname; + + const search = instantsearch({ + indexName, + searchClient: algoliasearch(appid, apikey), + searchFunction: helper => { + if (document.querySelector('.search-input').value) { + helper.search(); + } + } + }); + + const markKeyWords = function(content) { + return content.replaceAll("", ''); + }; + + if (typeof pjax === 'object') { + search.on('render', () => { + pjax.refresh(document.querySelector('.algolia-hits')); + }); + } + + // Registering Widgets + search.addWidgets([ + instantsearch.widgets.configure({ + hitsPerPage: hits.perpage || 10 + }), + + instantsearch.widgets.searchBox({ + container: '.search-input-container', + placeholder: NexT.CONFIG.i18n.placeholder, + // Hide default icons of algolia search + showReset: false, + showSubmit: false, + showLoadingIndicator: true, + cssClasses: { + input: 'search-input' + } + }), + + instantsearch.widgets.stats({ + container: '.algolia-stats', + templates: { + text: data => { + const stats = NexT.CONFIG.i18n.hits_time + .replace('${hits}', data.nbHits) + .replace('${time}', data.processingTimeMS); + return `${stats}Algolia`; + } + }, + cssClasses: { + text: 'search-stats' + } + }), + + instantsearch.widgets.hits({ + container: '.algolia-hits', + escapeHTML: true, + templates: { + item: data => { + const { title, content } = data._highlightResult; + let result = `${markKeyWords(title.value)}`; + //const content = excerpt || excerptStrip || content; + if (content && content.value) { + const div = document.createElement('div'); + div.innerHTML = markKeyWords(content.value); + result += `

${div.innerHTML.substring(0, 200)}...

`; + } + return result; + }, + empty: data => { + return `
+ ${NexT.CONFIG.i18n.empty.replace('${query}', data.query)} +
`; + } + }, + cssClasses: { + list: 'search-result-list' + } + }), + + instantsearch.widgets.pagination({ + container: '.algolia-pagination', + scrollTo: false, + showFirst: true, + showLast: true, + templates: { + first: '', + last: '', + previous: '', + next: '' + }, + cssClasses: { + list: ['pagination', 'algolia-pagination'], + item: 'pagination-item', + link: 'page-number', + selectedItem: 'current', + disabledItem: 'disabled-item' + } + }) + ]); + + search.start(); + + // Handle and trigger popup window + document.querySelectorAll('.popup-trigger').forEach(element => { + element.addEventListener('click', () => { + document.body.classList.add('search-active'); + setTimeout(() => document.querySelector('.search-input').focus(), 500); + }); + }); + + // Monitor main search box + const onPopupClose = () => { + document.body.classList.remove('search-active'); + }; + + document.querySelector('.search-pop-overlay').addEventListener('click', event => { + if (event.target === document.querySelector('.search-pop-overlay')) { + onPopupClose(); + } + }); + document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); + document.addEventListener('pjax:success', onPopupClose); + window.addEventListener('keyup', event => { + if (event.key === 'Escape') { + onPopupClose(); + } + }); + });; + + +}); \ No newline at end of file diff --git a/assets/js/third-party/search/local.js b/assets/js/third-party/search/local.js new file mode 100644 index 0000000..c2c238f --- /dev/null +++ b/assets/js/third-party/search/local.js @@ -0,0 +1,326 @@ +/* global CONFIG, pjax, LocalSearch */ +class LocalSearch { + constructor({ + path = '', + unescape = false, + top_n_per_article = 1 + }) { + this.path = path; + this.unescape = unescape; + this.top_n_per_article = top_n_per_article; + this.isfetched = false; + this.datas = null; + } + + getIndexByWord(words, text, caseSensitive = false) { + const index = []; + const included = new Set(); + + if (!caseSensitive) { + text = text.toLowerCase(); + } + words.forEach(word => { + if (this.unescape) { + const div = document.createElement('div'); + div.innerText = word; + word = div.innerHTML; + } + const wordLen = word.length; + if (wordLen === 0) return; + let startPosition = 0; + let position = -1; + if (!caseSensitive) { + word = word.toLowerCase(); + } + while ((position = text.indexOf(word, startPosition)) > -1) { + index.push({ position, word }); + included.add(word); + startPosition = position + wordLen; + } + }); + // Sort index by position of keyword + index.sort((left, right) => { + if (left.position !== right.position) { + return left.position - right.position; + } + return right.word.length - left.word.length; + }); + return [index, included]; + } + + // Merge hits into slices + mergeIntoSlice(start, end, index) { + let item = index[0]; + let { position, word } = item; + const hits = []; + const count = new Set(); + while (position + word.length <= end && index.length !== 0) { + count.add(word); + hits.push({ + position, + length: word.length + }); + const wordEnd = position + word.length; + + // Move to next position of hit + index.shift(); + while (index.length !== 0) { + item = index[0]; + position = item.position; + word = item.word; + if (wordEnd > position) { + index.shift(); + } else { + break; + } + } + } + return { + hits, + start, + end, + count: count.size + }; + } + + // Highlight title and content + highlightKeyword(val, slice) { + let result = ''; + let index = slice.start; + for (const { position, length } of slice.hits) { + result += val.substring(index, position); + index = position + length; + result += `${val.substr(position, length)}`; + } + result += val.substring(index, slice.end); + return result; + } + + getResultItems(keywords) { + const resultItems = []; + this.datas.forEach(({ title, content, url }) => { + // The number of different keywords included in the article. + const [indexOfTitle, keysOfTitle] = this.getIndexByWord(keywords, title); + const [indexOfContent, keysOfContent] = this.getIndexByWord(keywords, content); + const includedCount = new Set([...keysOfTitle, ...keysOfContent]).size; + + // Show search results + const hitCount = indexOfTitle.length + indexOfContent.length; + if (hitCount === 0) return; + + const slicesOfTitle = []; + if (indexOfTitle.length !== 0) { + slicesOfTitle.push(this.mergeIntoSlice(0, title.length, indexOfTitle)); + } + + let slicesOfContent = []; + while (indexOfContent.length !== 0) { + const item = indexOfContent[0]; + const { position } = item; + // Cut out 100 characters. The maxlength of .search-input is 80. + const start = Math.max(0, position - 20); + const end = Math.min(content.length, position + 80); + slicesOfContent.push(this.mergeIntoSlice(start, end, indexOfContent)); + } + + // Sort slices in content by included keywords' count and hits' count + slicesOfContent.sort((left, right) => { + if (left.count !== right.count) { + return right.count - left.count; + } else if (left.hits.length !== right.hits.length) { + return right.hits.length - left.hits.length; + } + return left.start - right.start; + }); + + // Select top N slices in content + const upperBound = parseInt(this.top_n_per_article, 10); + if (upperBound >= 0) { + slicesOfContent = slicesOfContent.slice(0, upperBound); + } + + let resultItem = ''; + + url = new URL(url, location.origin); + url.searchParams.append('highlight', keywords.join(' ')); + + if (slicesOfTitle.length !== 0) { + resultItem += `
  • ${this.highlightKeyword(title, slicesOfTitle[0])}`; + } else { + resultItem += `
  • ${title}`; + } + + slicesOfContent.forEach(slice => { + resultItem += `

    ${this.highlightKeyword(content, slice)}...

    `; + }); + + resultItem += '
  • '; + resultItems.push({ + item: resultItem, + id : resultItems.length, + hitCount, + includedCount + }); + }); + return resultItems; + } + + fetchData() { + const isXml = !this.path.endsWith('json'); + fetch(this.path) + .then(response => response.text()) + .then(res => { + // Get the contents from search data + this.isfetched = true; + this.datas = isXml ? [...new DOMParser().parseFromString(res, 'text/xml').querySelectorAll('entry')].map(element => ({ + title : element.querySelector('title').textContent, + content: element.querySelector('content').textContent, + url : element.querySelector('url').textContent + })) : JSON.parse(res); + // Only match articles with non-empty titles + this.datas = this.datas.filter(data => data.title).map(data => { + data.title = data.title.trim(); + data.content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : ''; + data.url = decodeURIComponent(data.url).replace(/\/{2,}/g, '/'); + return data; + }); + // Remove loading animation + window.dispatchEvent(new Event('search:loaded')); + }); + } + + // Highlight by wrapping node in mark elements with the given class name + highlightText(node, slice, className) { + const val = node.nodeValue; + let index = slice.start; + const children = []; + for (const { position, length } of slice.hits) { + const text = document.createTextNode(val.substring(index, position)); + index = position + length; + const mark = document.createElement('mark'); + mark.className = className; + mark.appendChild(document.createTextNode(val.substr(position, length))); + children.push(text, mark); + } + node.nodeValue = val.substring(index, slice.end); + children.forEach(element => { + node.parentNode.insertBefore(element, node); + }); + } + + // Highlight the search words provided in the url in the text + highlightSearchWords(body) { + const params = new URL(location.href).searchParams.get('highlight'); + const keywords = params ? params.split(' ') : []; + if (!keywords.length || !body) return; + const walk = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, null); + const allNodes = []; + while (walk.nextNode()) { + if (!walk.currentNode.parentNode.matches('button, select, textarea')) allNodes.push(walk.currentNode); + } + allNodes.forEach(node => { + const [indexOfNode] = this.getIndexByWord(keywords, node.nodeValue); + if (!indexOfNode.length) return; + const slice = this.mergeIntoSlice(0, node.nodeValue.length, indexOfNode); + this.highlightText(node, slice, 'search-keyword'); + }); + } +} + +document.addEventListener('DOMContentLoaded', () => { + if (! NexT.CONFIG.localSearch.path) { + // Search DB path + console.warn('`search indexes file` is not configurate!'); + return; + } + const localSearch = new LocalSearch({ + path : NexT.CONFIG.localSearch.path, + top_n_per_article: NexT.CONFIG.localSearch.topnperarticle, + unescape : NexT.CONFIG.localSearch.unescape + }); + + const input = document.querySelector('.search-input'); + + const inputEventFunction = () => { + if (!localSearch.isfetched) return; + const searchText = input.value.trim().toLowerCase(); + const keywords = searchText.split(/[-\s]+/); + const container = document.querySelector('.search-result-container'); + let resultItems = []; + if (searchText.length > 0) { + // Perform local searching + resultItems = localSearch.getResultItems(keywords); + } + if (keywords.length === 1 && keywords[0] === '') { + container.classList.add('no-result'); + container.innerHTML = '
    '; + } else if (resultItems.length === 0) { + container.classList.add('no-result'); + container.innerHTML = '
    '; + } else { + resultItems.sort((left, right) => { + if (left.includedCount !== right.includedCount) { + return right.includedCount - left.includedCount; + } else if (left.hitCount !== right.hitCount) { + return right.hitCount - left.hitCount; + } + return right.id - left.id; + }); + const stats = NexT.CONFIG.i18n.hits.replace('${hits}', resultItems.length); + + container.classList.remove('no-result'); + container.innerHTML = `
    ${stats}
    +
    + `; + if (typeof pjax === 'object') pjax.refresh(container); + } + }; + + localSearch.highlightSearchWords(document.querySelector('.post-body')); + if (NexT.CONFIG.localSearch.preload) { + localSearch.fetchData(); + } + + if (NexT.CONFIG.localSearch.trigger === 'auto') { + input.addEventListener('input', inputEventFunction); + } else { + document.querySelector('.search-icon').addEventListener('click', inputEventFunction); + input.addEventListener('keypress', event => { + if (event.key === 'Enter') { + inputEventFunction(); + } + }); + } + window.addEventListener('search:loaded', inputEventFunction); + + // Handle and trigger popup window + document.querySelectorAll('.popup-trigger').forEach(element => { + element.addEventListener('click', () => { + document.body.classList.add('search-active'); + // Wait for search-popup animation to complete + setTimeout(() => input.focus(), 500); + if (!localSearch.isfetched) localSearch.fetchData(); + }); + }); + + // Monitor main search box + const onPopupClose = () => { + document.body.classList.remove('search-active'); + }; + + document.querySelector('.search-pop-overlay').addEventListener('click', event => { + if (event.target === document.querySelector('.search-pop-overlay')) { + onPopupClose(); + } + }); + document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); + document.addEventListener('pjax:success', () => { + localSearch.highlightSearchWords(document.querySelector('.post-body')); + onPopupClose(); + }); + window.addEventListener('keyup', event => { + if (event.key === 'Escape') { + onPopupClose(); + } + }); +}); diff --git a/data/config.yaml b/data/config.yaml index 8ca6ecf..ee220a7 100644 --- a/data/config.yaml +++ b/data/config.yaml @@ -1,4 +1,4 @@ # Hugo NexT theme's custom config # -version: 4.1.0 \ No newline at end of file +version: 4.2.0 \ No newline at end of file diff --git a/data/resources.yaml b/data/resources.yaml index e95a2f7..f039b4c 100644 --- a/data/resources.yaml +++ b/data/resources.yaml @@ -39,8 +39,8 @@ analytics: addthis: js: https://s7.addthis.com/js/300/addthis_widget.js -# 评论组件资源 -# Comment component Resources +# 评论组件 +# Comment component waline: js: name: '@waline/client' @@ -70,4 +70,15 @@ utterances: js: https://utteranc.es/client.js livere: - js: https://cdn-city.livere.com/js/embed.dist.js \ No newline at end of file + js: https://cdn-city.livere.com/js/embed.dist.js + +# 全文搜索 +# Full text search +algolia: + name: algoliasearch + version: 4.13.0 + file: dist/algoliasearch-lite.umd.js +instant: + name: instantsearch.js + version: 4.40.5 + file: dist/instantsearch.production.min.js \ No newline at end of file diff --git a/exampleSite/config.yaml b/exampleSite/config.yaml index 0536ba9..e832f90 100644 --- a/exampleSite/config.yaml +++ b/exampleSite/config.yaml @@ -55,6 +55,42 @@ markup: endLevel: 3 ordered: false +# 站点文章导航文件 +# Site map of all articles +sitemap: + filename: "sitemap.xml" + changefreq: "weekly" + priority: 0.5 + +outputFormats: + RSS: + baseName: "rss" + # 自定义生成本地搜索文件 + # Custom file of indexes for local search + LocalIndexes: + mediaType: application/xml + baseName: searchindexes + isPlainText: true + notAlternative: true + # 生成 Algolia 索引文件 + # Build indexes of Aloglia + AlgoliaIndexes: + mediaType: application/json + baseName: algolia + isPlainText: true + notAlternative: true + +# 默认使用本地搜索,如切换到 Algolia 搜索引擎, +# 请将下面的 LocalIndexes 替换成 AlgoliaIndexes +# By default use local search, before switch to Algolia engine +# Please replace LocalIndexes with AlgoliaIndexes +outputs: + home: ["HTML", "RSS", "LocalIndexes"] + +# 输出 robots 文件支持爬虫扫描 +# Enable robots with support crawler scan +enableRobotsTXT: true + #-------------------------------------- # 菜单配置说明 # identifier : 唯一标识不可重复 @@ -84,16 +120,21 @@ menus: pageref: /about.html pre: user weight: 2 + - identifier: flinks + name: 站点示例 + pageref: /flinks.html + pre: thumbs-up + weight: 3 - identifier: archives name: 归档 pageref: /archives pre: archive - weight: 3 + weight: 4 - identifier: commonweal name: 公益 404 url: /404.html pre: heartbeat - weight: 4 + weight: 5 #----------------------------------------- # Hugo NexT 主题参数配置 @@ -877,8 +918,7 @@ params: # --------------------------------------------------------------- - # TODO - # 内容搜索服务(暂时未实现) + # 内容搜索服务 # Search Services # --------------------------------------------------------------- @@ -886,19 +926,32 @@ params: # For more information: https://www.algolia.com algoliaSearch: enable: false + appId: # + apiKey: # + indexName: # hits: perPage: 10 + # 本地搜索 # Local Search localSearch: + # 是否开启搜索功能 + # Enable search function enable: true + # 搜索索引文件路径 + # Indexes file path for search + path: searchindexes.xml + # 是立即搜索当输入关键字时,可选值: auto | manual # If auto, trigger search by changing input. # If manual, trigger search by pressing enter key or search button. trigger: auto + # 显示头部的搜索记录,-1 表示显示所有搜索结果 # Show top n results per article, show all results by setting to -1 - top_n_per_article: 1 + topNPerArticle: -1 + # 将 html 字符串转换为可读字符串 # Unescape html strings to the readable one. unescape: false + # 页面加载时是否要重新载入索引文件 # Preload the search data when the page loads. preload: false diff --git a/exampleSite/content/about.md b/exampleSite/content/about.md new file mode 100644 index 0000000..c4e89c7 --- /dev/null +++ b/exampleSite/content/about.md @@ -0,0 +1,27 @@ +--- +title: "关于 Hugo NexT 组织" +description: "Hugo NexT 组织介绍说明。" + +date: 2022-06-09T20:12:52+08:00 +lastmod: 2022-06-09T20:12:52+08:00 + +share: false +followme: false +nav: false +copyright: false +url: about.html +--- + +`Hugo NexT` 组织是由众多喜爱 `NexT` 主题及风格的世界各地友人共同组建而成,为的就是让这个主题继续在 `Hugo` 引擎中也能得到发扬光大,在此也欢迎你的加入! + +# 我们的愿景 + +延续 `NexT` 经典的黑白调搭配,保持简单的易用性及强大的功能。 + +# 使用反馈 + +- 加入 [GitHub Discussions](https://github.com/hugo-next/hugo-theme-next/discussions) 或 [Gitter](https://gitter.im/hugo-next/community) 在线讨论 :beers: +- [GitHub Issues](https://github.com/hugo-next/hugo-theme-next/issues/new?labels=Bug&template=bug-report.md) 提交错误报告 :bug: +- [GitHub Feature](https://github.com/hugo-next/hugo-theme-next/issues/new?labels=Feature+Request&template=feature-request.md) 表新功能的想法 :sparkles: + +> 同时国内用户也可加入 QQ 群交流: 604710815 \ No newline at end of file diff --git a/exampleSite/content/flinks.md b/exampleSite/content/flinks.md new file mode 100644 index 0000000..525f67e --- /dev/null +++ b/exampleSite/content/flinks.md @@ -0,0 +1,16 @@ +--- +title: "站点示例" +type: flinks +url: flinks.html +--- + +如想要交换友情链接,请在评论区留下你的站点信息,格式参考如下: + +{{< note success no-icon >}} + + **名称:** NexT 主题
    + **说明:** 保持简单的易用性和强大的功能。
    + **站标:** https://hugo-next.eu.org/imgs/hugo_next_avatar.png
    + **网址:** https://hugo-next.eu.org
    + +{{< /note >}} \ No newline at end of file diff --git a/exampleSite/content/post/shortcodes.md b/exampleSite/content/post/shortcodes.md new file mode 100644 index 0000000..c6be592 --- /dev/null +++ b/exampleSite/content/post/shortcodes.md @@ -0,0 +1,86 @@ +--- +title: "自定义短语示例" +description: "将常用的块引用、标签卡、按钮等信息设置成短代码,便于快速引用" +keywords: "shortcode,短代码" + +date: 2022-08-06T14:41:50+08:00 +lastmod: 2022-08-06T14:41:50+08:00 + +categories: + - 示例 +tags: + - 短代码 + - 语法 +url: "post/shortcodes.html" +--- + +虽然 `Markdown` 语法已经非常丰富能够满足我们写文章的绝大部分需求,但是为更好的对文章内容进行更友好的排版,为引设计一套自定义的短语,便于在使用时能够快速引用。 + + + +# 块引用 + +在引用一些经典名言名句时,可以采用此短语,语法参考如下: + +```markdown +{{}} + ### block quote + 写下你想表达的话语! +{{}} +``` + +实际效果: + +{{< quote >}} + +希望是无所谓有,无所谓无的,这正如地上的路。 + + +其实地上本没有路,走的人多了,也便成了路。 + +**鲁迅** + +{{< /quote >}} + +# 信息块 + +支持 `default`,`info`,`success`,`warning`,`danger` 等五种不同效果的展示,语法参考如下: + +```markdown +{{}} + 书写表达的信息 + 支持 Markdown 语法 +{{}} +``` + +实际效果: + +{{< note default no-icon >}} + ### Default Header without icon + **Welcome** to [Hugo NexT!](https://preview.hugo-next.eu.org) +{{< /note >}} + +{{< note default >}} + ### Default Header + **Welcome** to [Hugo NexT!](https://preview.hugo-next.eu.org) +{{< /note >}} + +{{< note info >}} + ### Info Header + **Welcome** to [Hugo NexT!](https://preview.hugo-next.eu.org) +{{< /note >}} + +{{< note success >}} + ### Success Header + **Welcome** to [Hugo NexT!](https://preview.hugo-next.eu.org) +{{< /note >}} + +{{< note warning >}} + ### Warning Header + **Welcome** to [Hugo NexT!](https://preview.hugo-next.eu.org) +{{< /note >}} + +{{< note danger >}} + ### Danger Header + **Welcome** to [Hugo NexT!](https://preview.hugo-next.eu.org) +{{< /note >}} diff --git a/exampleSite/data/flinks.yaml b/exampleSite/data/flinks.yaml new file mode 100644 index 0000000..3a43c14 --- /dev/null +++ b/exampleSite/data/flinks.yaml @@ -0,0 +1,29 @@ +# 友情链接 +# Friend's links + +- FLinksTitle: 官方示例 + FLinksDesc: 来自主题官方的示例内容。 + FLinksList: + - name: Hugo + desc: 世界上最快的网站建设框架! + avatar: https://gohugo.io/favicon-32x32.png + link: https://gohugo.io + + - name: Hugo-NexT + desc: Hugo NexT 官方预览网站。 + avatar: https://hugo-next.eu.org/imgs/hugo_next_avatar.png + link: https://hugo-next.eu.org + + - name: 凡梦星尘空间站 + desc: 再平凡的人也有属于他的梦想! + avatar: https://lisenhui.cn/img/avatar.png + link: https://lisenhui.cn + + +- FLinksTitle: Hugo NexT 粉丝群体 + FLinksDesc: 来自 Hugo NexT 主题爱好者们的精彩呈现! + FLinksList: + - name: 阿哈吉 + desc: 全网首个 Hugo NexT 忠实粉丝用户 + avatar: https://a.happy2008.top/imgs/stayhome-small.png + link: https://a.happy2008.top/ \ No newline at end of file diff --git a/exampleSite/start.sh b/exampleSite/start.sh index 59f814c..ff1ab60 100644 --- a/exampleSite/start.sh +++ b/exampleSite/start.sh @@ -20,4 +20,4 @@ EOT next `cat ../VERSION` -hugo server -D -t ../.. --port 1414 --panicOnWarning --config config.dev.yaml +hugo server -t ../.. --port 1414 --panicOnWarning --config config.yaml diff --git a/i18n/en.yaml b/i18n/en.yaml index a7ca413..65f0158 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -140,4 +140,13 @@ PageViewsLabel: other: Total Page Views FooterPowerby: - other: "Power by %s" \ No newline at end of file + other: "Power by %s" + +SearchPh: + other: Searching... +SearchEmpty: + other: "We didn't find any results for the search: ${query}" +SearchHits: + hits: "${hits} results found" +SearchHitsTime: + other: "${hits} results found in ${time} ms" \ No newline at end of file diff --git a/i18n/zh-cn.yaml b/i18n/zh-cn.yaml index 1aa9600..a0b30be 100644 --- a/i18n/zh-cn.yaml +++ b/i18n/zh-cn.yaml @@ -141,4 +141,13 @@ PageViewsLabel: other: 总访问量 FooterPowerby: - other: 由 %s 强力驱动 \ No newline at end of file + other: 由 %s 强力驱动 + +SearchPh: + other: 搜索... +SearchEmpty: + other: "没有找到任何搜索结果:${query}" +SearchHits: + hits: "找到 ${hits} 个搜索结果" +SearchHitsTime: + other: "找到 ${hits} 个搜索结果(用时 ${time} 毫秒)" \ No newline at end of file diff --git a/layouts/_default/list.algoliaindexes.json b/layouts/_default/list.algoliaindexes.json new file mode 100644 index 0000000..91124c1 --- /dev/null +++ b/layouts/_default/list.algoliaindexes.json @@ -0,0 +1,12 @@ +[ + {{- range $index, $entry := where .Site.RegularPages "Kind" "page" }} + {{- if $index }}, {{ end }} + { + "permalink": "{{ .Permalink | relURL }}", + "title": {{ .Title | jsonify }}, + "content": {{ .Plain | jsonify }}, + "date": {{ .Date.Format $.Site.Params.timeFormat | jsonify }}, + "updated": {{ .Lastmod.Format $.Site.Params.timeFormat | jsonify }} + } + {{- end }} +] \ No newline at end of file diff --git a/layouts/_default/list.html b/layouts/_default/list.html index 19015ab..ea48856 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -1,7 +1,3 @@ -{{- if and .Page.IsSection (eq .Section "archives") }} - {{- $paginator := (.Paginate (where .Page.Site.RegularPages "Section" "in" .Site.Params.mainSections)).Pages.GroupByDate "2006" }} - {{ partial "list.html" $paginator }} -{{ else }} - {{- $paginator := .Paginator.Pages.GroupByDate "2006" }} - {{ partial "list.html" $paginator }} -{{- end }} +{{ $paginator := .Paginator.Pages.GroupByDate "2006" }} +{{ partial "list.html" $paginator }} + diff --git a/layouts/_default/list.localindexes.xml b/layouts/_default/list.localindexes.xml new file mode 100644 index 0000000..ea75b7b --- /dev/null +++ b/layouts/_default/list.localindexes.xml @@ -0,0 +1,18 @@ +{{ printf "" | safeHTML }} + + {{range where .Site.RegularPages "Kind" "page"}} + + {{ .Title }} + {{ .Permalink }} + + {{- range .Params.categories }}{{ . }}{{- end }} + + + {{- range .Params.tags }} + {{ . }} + {{- end }} + + + + {{ end }} + \ No newline at end of file diff --git a/layouts/_default/section.html b/layouts/_default/section.html index 9e73648..1c9ea69 100644 --- a/layouts/_default/section.html +++ b/layouts/_default/section.html @@ -1,39 +1,15 @@ {{- define "title" }} -{{- .Params.Title | default (T .Section) | default .Section | dict "Some" | T "AllSome" }} - {{ .Site.Title -}} +{{- .Params.Title | default (T .Section) | default .Section }} - {{ .Site.Title -}} {{- end -}} -{{ define "main_inner_class" }}archive posts-collapse{{ end }} -{{- define "main" }} -
    -
    -
    - {{- $cheers := "Um" }} - {{- $posts := .Scratch.Get "postsCount" }} - {{- if and .Page.IsSection (ne .Section "archives") }} - {{- $posts = .Scratch.Get .Section }} - {{- end }} - {{- if gt $posts 210 }} - {{- $cheers = "Excellent" }} - {{- else if gt $posts 130 }} - {{- $cheers = "Great" }} - {{- else if gt $posts 80 }} - {{- $cheers = "Good" }} - {{- else if gt $posts 50 }} - {{- $cheers = "Nice" }} - {{- else if gt $posts 30 }} - {{- $cheers = "Ok" }} - {{- end }} - - {{- T (printf "PostArchiveCheers%s" $cheers) }} - {{- T "SymbolComma" }} - {{- T "ArchiveCounterTitle" $posts | safeHTML }} - {{- T "SymbolComma" }} - {{- T "PostArchiveKeepOn" }} - -
    +{{ define "main_inner_class" }}index posts-expand{{ end }} - {{ .Render "list" }} - -
    -
    -{{- partial "pagination.html" . }} +{{- define "main" }} + +{{ $paginator := .Paginate (where .Site.RegularPages "Section" "==" .Section) }} +{{- range $paginator.Pages }} + {{ partial "post.html" (dict "ctx" . "IsHome" true) }} +{{- end }} + +{{- partial "partials/pagination.html" . }} + {{- end }} \ No newline at end of file diff --git a/layouts/archives/list.html b/layouts/archives/list.html new file mode 100644 index 0000000..cc63576 --- /dev/null +++ b/layouts/archives/list.html @@ -0,0 +1,2 @@ +{{ $paginator := (.Paginate (where .Page.Site.RegularPages "Section" "in" .Site.Params.mainSections)).Pages.GroupByDate "2006" }} +{{ partial "list.html" $paginator }} \ No newline at end of file diff --git a/layouts/archives/section.html b/layouts/archives/section.html new file mode 100644 index 0000000..17aba2f --- /dev/null +++ b/layouts/archives/section.html @@ -0,0 +1,36 @@ +{{- define "title" }} +{{- .Params.Title | default (T .Section) | default .Section | dict "Some" | T "AllSome" }} - {{ .Site.Title -}} +{{- end -}} +{{ define "main_inner_class" }}archive posts-collapse{{ end }} +{{- define "main" }} +
    +
    +
    + {{- $cheers := "Um" }} + {{- $posts := .Scratch.Get "postsCount" }} + {{- if gt $posts 210 }} + {{- $cheers = "Excellent" }} + {{- else if gt $posts 130 }} + {{- $cheers = "Great" }} + {{- else if gt $posts 80 }} + {{- $cheers = "Good" }} + {{- else if gt $posts 50 }} + {{- $cheers = "Nice" }} + {{- else if gt $posts 30 }} + {{- $cheers = "Ok" }} + {{- end }} + + {{- T (printf "PostArchiveCheers%s" $cheers) }} + {{- T "SymbolComma" }} + {{- T "ArchiveCounterTitle" $posts | safeHTML }} + {{- T "SymbolComma" }} + {{- T "PostArchiveKeepOn" }} + +
    + + {{ .Render "list" }} + +
    +
    +{{- partial "pagination.html" . }} +{{- end }} \ No newline at end of file diff --git a/layouts/flinks/single.html b/layouts/flinks/single.html new file mode 100644 index 0000000..cbe325d --- /dev/null +++ b/layouts/flinks/single.html @@ -0,0 +1,34 @@ +{{- define "title" }}{{- .Title }} - {{ .Site.Title -}}{{- end }} + +{{- define "main_inner_class" }}flinks posts-expand{{- end }} + +{{ define "main" }} + + + +{{ end }} \ No newline at end of file diff --git a/layouts/index.html b/layouts/index.html index 50f5ee0..1f743de 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -1,8 +1,11 @@ {{- define "main_inner_class" }}index posts-expand{{- end }} + {{- define "main" }} + {{ $paginator := .Paginate (where .Site.RegularPages "Section" "in" .Site.Params.mainSections) }} {{- range $paginator.Pages }} -{{ partial "post.html" (dict "ctx" . "IsHome" true) }} + {{ partial "post.html" (dict "ctx" . "IsHome" true) }} {{- end }} + {{- partial "partials/pagination.html" . }} {{- end }} \ No newline at end of file diff --git a/layouts/partials/_thirdparty/search/algolia.html b/layouts/partials/_thirdparty/search/algolia.html new file mode 100644 index 0000000..81e67c0 --- /dev/null +++ b/layouts/partials/_thirdparty/search/algolia.html @@ -0,0 +1,14 @@ +
    + + + +
    + + + +
    +
    +

    +
    +
    +
    \ No newline at end of file diff --git a/layouts/partials/_thirdparty/search/local.html b/layouts/partials/_thirdparty/search/local.html new file mode 100644 index 0000000..d67006a --- /dev/null +++ b/layouts/partials/_thirdparty/search/local.html @@ -0,0 +1,18 @@ +
    + + + +
    + +
    + + + +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/layouts/partials/head/style.html b/layouts/partials/head/style.html index 4e2d1ab..c793eed 100644 --- a/layouts/partials/head/style.html +++ b/layouts/partials/head/style.html @@ -27,7 +27,7 @@ {{- if .IsPage }} diff --git a/layouts/partials/header.html b/layouts/partials/header.html index 01f3aaa..956a531 100644 --- a/layouts/partials/header.html +++ b/layouts/partials/header.html @@ -1,2 +1,3 @@ {{ partial "header/brand.html" . }} -{{ partial "header/menus.html" . }} \ No newline at end of file +{{ partial "header/menus.html" . }} +{{ partial "header/search.html" . }} \ No newline at end of file diff --git a/layouts/partials/header/search.html b/layouts/partials/header/search.html new file mode 100644 index 0000000..00353b8 --- /dev/null +++ b/layouts/partials/header/search.html @@ -0,0 +1,11 @@ +{{- if or .Site.Params.algoliaSearch.enable .Site.Params.localSearch.enable }} +
    + +
    +{{- end }} \ No newline at end of file diff --git a/layouts/partials/init.html b/layouts/partials/init.html index 5ceb18a..22f8872 100644 --- a/layouts/partials/init.html +++ b/layouts/partials/init.html @@ -1,22 +1,20 @@ {{/* Use to defind global variables */}} -{{ if not hugo.IsExtended }} -{{ warnf "Hugo NexT 主题使用了 SCSS 框架,请到官方地址下载 Hugo Extended 版本:https://github.com/gohugoio/hugo/releases" }} -{{ errorf "Because that use SCSS framework in Hugo NexT, Please download Hugo extended version on offical site: https://github.com/gohugoio/hugo/releases" }} -{{ end }} - {{ $version := int (index (split hugo.Version ".") 1) }} {{ if lt $version 89 }} -{{ warnf "当前 Hugo 版本小于 0.89.0,请到官方地址下载 Hugo 最新版本:https://github.com/gohugoio/hugo/releases" }} -{{ errorf "Current Hugo version is less then 0.89.0, Please download Hugo latest version on offical site: https://github.com/gohugoio/hugo/releases" }} + {{ warnf "当前 Hugo 版本小于 0.89.0,请到官方地址下载 Hugo 最新版本:https://github.com/gohugoio/hugo/releases" }} + {{ errorf "Current Hugo version is less then 0.89.0, Please download Hugo latest version on offical site: https://github.com/gohugoio/hugo/releases" }} {{ end }} +{{ if not hugo.IsExtended }} + {{ warnf "Hugo NexT 主题使用了 SCSS 框架,请到官方地址下载 Hugo Extended 版本:https://github.com/gohugoio/hugo/releases" }} + {{ errorf "Because that use SCSS framework in Hugo NexT, Please download Hugo extended version on offical site: https://github.com/gohugoio/hugo/releases" }} +{{ end }} + + {{ $globalVars := newScratch }} {{ $globalVars.Set "postsCount" (len (where .Page.Site.RegularPages "Section" "in" .Site.Params.mainSections)) }} -{{ range .Site.Params.mainSections }} - {{ $globalVars.Set . (len (where $.Page.Site.RegularPages "Section" .))}} -{{ end }} {{ $globalVars.Set "catsCount" (len .Site.Taxonomies.categories) }} {{ $globalVars.Set "tagsCount" (len .Site.Taxonomies.tags) }} @@ -25,20 +23,40 @@ {{ $globalVars.Set "router" $router }} {{ $config := dict - "hostname" .Site.BaseURL - "root" "/" - "lang" .Site.LanguageCode - "vendor" (dict "plugins" $vendor "router" $router) - "darkmode" .Site.Params.darkmode - "version" .Site.Data.config.version - "scheme" .Site.Params.scheme - "sidebar" .Site.Params.sidebar - "copybtn" .Site.Params.codeblock.copyBtn - "bookmark" .Site.Params.bookmark - "lazyload" .Site.Params.lazyload - "motion" .Site.Params.motion + "hostname" .Site.BaseURL + "root" "/" + "lang" .Site.LanguageCode + "vendor" (dict "plugins" $vendor "router" $router) + "darkmode" .Site.Params.darkmode + "version" .Site.Data.config.version + "scheme" .Site.Params.scheme + "sidebar" .Site.Params.sidebar + "copybtn" .Site.Params.codeblock.copyBtn + "bookmark" .Site.Params.bookmark + "lazyload" .Site.Params.lazyload + "motion" .Site.Params.motion + "i18n" (dict + "placeholder" (T "SearchPh") + "empty" (T "SearchEmpty") + "hits_time" (T "SearchHitsTime") + "hits" (T "SearchHits") + ) }} +{{ if .Site.Params.localSearch.enable }} + {{ $localSearch := dict "localSearch" .Site.Params.localSearch }} + {{ $config = merge $config $localSearch }} +{{ end }} + +{{ if .Site.Params.algoliaSearch.enable }} + {{ $algoliaSearch := dict + "js" .Site.Data.resources.algolia + "instantjs" .Site.Data.resources.instant + "cfg" .Site.Params.algoliaSearch + }} + {{ $config = merge $config (dict "algolia" $algoliaSearch) }} +{{ end }} + {{ with .Site.Params.waline }} {{ $waline := dict "js" $.Site.Data.resources.waline.js diff --git a/layouts/partials/list.html b/layouts/partials/list.html index 7ddf390..82fd9b0 100644 --- a/layouts/partials/list.html +++ b/layouts/partials/list.html @@ -6,8 +6,8 @@
    @@ -18,7 +18,7 @@ {{- else }} - {{- end }} diff --git a/layouts/partials/post/footer.html b/layouts/partials/post/footer.html index 0a88841..cffa3eb 100644 --- a/layouts/partials/post/footer.html +++ b/layouts/partials/post/footer.html @@ -25,15 +25,15 @@
    {{- with .NextInSection }} - {{- end }}
    {{- with .PrevInSection }} - {{- end }} diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index 0b4a23c..4015bd1 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -64,8 +64,17 @@ {{- $utterancesjs := resources.Get "js/third-party/comments/utterances.js" }} {{- $nextjs = $nextjs | append $utterancesjs }} {{- end }} +{{- if .Site.Params.localSearch.enable }} +{{- $search := resources.Get "js/third-party/search/local.js" }} +{{- $nextjs = $nextjs | append $search }} +{{ end }} +{{- if .Site.Params.algoliaSearch.enable }} +{{- $search := resources.Get "js/third-party/search/algolia.js" }} +{{- $nextjs = $nextjs | append $search }} +{{ end }} {{- $nextjs = $nextjs | resources.Concat "js/main.js"}} {{ if hugo.IsProduction }} {{- $nextjs = $nextjs | minify | fingerprint }} {{ end }} - \ No newline at end of file + + diff --git a/layouts/partials/sidebar/overview.html b/layouts/partials/sidebar/overview.html index ec8b889..978ec5d 100644 --- a/layouts/partials/sidebar/overview.html +++ b/layouts/partials/sidebar/overview.html @@ -12,7 +12,7 @@