From 6cbffe48b73dc06688e3d2c6bf2bf2f72de2c86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sat, 30 Jul 2022 17:39:57 +0800 Subject: [PATCH 01/29] :wrench: Re Change default section display not use archive page. --- .gitignore | 3 ++- exampleSite/content/about.md | 27 +++++++++++++++++++++ exampleSite/start.sh | 2 +- layouts/_default/list.html | 10 +++----- layouts/_default/section.html | 44 ++++++++--------------------------- layouts/archives/list.html | 2 ++ layouts/archives/section.html | 36 ++++++++++++++++++++++++++++ layouts/index.html | 5 +++- layouts/partials/init.html | 18 +++++++------- layouts/partials/list.html | 4 ++-- 10 files changed, 95 insertions(+), 56 deletions(-) create mode 100644 exampleSite/content/about.md create mode 100644 layouts/archives/list.html create mode 100644 layouts/archives/section.html diff --git a/.gitignore b/.gitignore index 6b89457..ac41c2c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,9 @@ exampleSite/* # Exclude special files in content folder +exampleSite/content/**/ !exampleSite/content -exampleSite/content/* +!exmapleSite/content/about.md !exampleSite/content/archives !exampleSite/content/post diff --git a/exampleSite/content/about.md b/exampleSite/content/about.md new file mode 100644 index 0000000..ca58c5f --- /dev/null +++ b/exampleSite/content/about.md @@ -0,0 +1,27 @@ +--- +title: "关于 Hugo NexT 组织" +description: "" + +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/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/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/section.html b/layouts/_default/section.html index 9e73648..6c2dfba 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 -}} {{- 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/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/init.html b/layouts/partials/init.html index 5ceb18a..3fd640a 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) }} diff --git a/layouts/partials/list.html b/layouts/partials/list.html index 7ddf390..5c6f55d 100644 --- a/layouts/partials/list.html +++ b/layouts/partials/list.html @@ -6,8 +6,8 @@
From 9a4883832f5aae537b307afa44eef6b53af6eb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sun, 31 Jul 2022 11:02:55 +0800 Subject: [PATCH 02/29] :wrench: :seedling: Complete the local search feature. --- .../js/third-party/search/algolia-search.js | 0 assets/js/third-party/search/local-search.js | 326 ++++++++++++++++++ exampleSite/config.yaml | 33 +- i18n/en.yaml | 11 +- i18n/zh-cn.yaml | 11 +- layouts/_default/list.searchindexes.xml | 18 + .../partials/_thirdparty/search/algolia.html | 14 + .../partials/_thirdparty/search/local.html | 18 + layouts/partials/header.html | 3 +- layouts/partials/header/search.html | 11 + layouts/partials/init.html | 31 +- layouts/partials/scripts.html | 5 +- static/js/third-party/search/local-search.js | 99 ------ theme.toml | 2 +- 14 files changed, 465 insertions(+), 117 deletions(-) rename {static => assets}/js/third-party/search/algolia-search.js (100%) create mode 100644 assets/js/third-party/search/local-search.js create mode 100644 layouts/_default/list.searchindexes.xml create mode 100644 layouts/partials/_thirdparty/search/algolia.html create mode 100644 layouts/partials/_thirdparty/search/local.html create mode 100644 layouts/partials/header/search.html delete mode 100644 static/js/third-party/search/local-search.js diff --git a/static/js/third-party/search/algolia-search.js b/assets/js/third-party/search/algolia-search.js similarity index 100% rename from static/js/third-party/search/algolia-search.js rename to assets/js/third-party/search/algolia-search.js diff --git a/assets/js/third-party/search/local-search.js b/assets/js/third-party/search/local-search.js new file mode 100644 index 0000000..c2c238f --- /dev/null +++ b/assets/js/third-party/search/local-search.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}
    +
    +
      ${resultItems.map(result => result.item).join('')}
    `; + 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/exampleSite/config.yaml b/exampleSite/config.yaml index 0536ba9..4a3f898 100644 --- a/exampleSite/config.yaml +++ b/exampleSite/config.yaml @@ -55,6 +55,27 @@ 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 + SearchIndexes: + mediaType: "application/xml" + baseName: "searchindexes" + isPlainText: true + notAlternative: true + +outputs: + home: ["HTML", "RSS", "SearchIndexes"] + #-------------------------------------- # 菜单配置说明 # identifier : 唯一标识不可重复 @@ -889,16 +910,26 @@ params: 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/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.searchindexes.xml b/layouts/_default/list.searchindexes.xml new file mode 100644 index 0000000..ea75b7b --- /dev/null +++ b/layouts/_default/list.searchindexes.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/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/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 3fd640a..34aef75 100644 --- a/layouts/partials/init.html +++ b/layouts/partials/init.html @@ -23,18 +23,25 @@ {{ $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 + "localSearch" .Site.Params.localSearch + "i18n" (dict + "placeholder" (T "SearchPh") + "empty" (T "SearchEmpty") + "hits_time" (T "SearchHitsTime") + "hits" (T "SearchHits") + ) }} {{ with .Site.Params.waline }} diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index 0b4a23c..f7ac6dd 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -68,4 +68,7 @@ {{ if hugo.IsProduction }} {{- $nextjs = $nextjs | minify | fingerprint }} {{ end }} - \ No newline at end of file + +{{- $search := resources.Get "js/third-party/search/local-search.js" }} + + diff --git a/static/js/third-party/search/local-search.js b/static/js/third-party/search/local-search.js deleted file mode 100644 index 92a264d..0000000 --- a/static/js/third-party/search/local-search.js +++ /dev/null @@ -1,99 +0,0 @@ -/* global CONFIG, pjax, LocalSearch */ - -document.addEventListener('DOMContentLoaded', () => { - if (!CONFIG.path) { - // Search DB path - console.warn('`hexo-generator-searchdb` plugin is not installed!'); - return; - } - const localSearch = new LocalSearch({ - path : CONFIG.path, - top_n_per_article: CONFIG.localsearch.top_n_per_article, - unescape : 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 = CONFIG.i18n.hits.replace('${hits}', resultItems.length); - - container.classList.remove('no-result'); - container.innerHTML = `
    ${stats}
    -
    -
      ${resultItems.map(result => result.item).join('')}
    `; - if (typeof pjax === 'object') pjax.refresh(container); - } - }; - - localSearch.highlightSearchWords(document.querySelector('.post-body')); - if (CONFIG.localsearch.preload) { - localSearch.fetchData(); - } - - if (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/theme.toml b/theme.toml index 3d6831f..eae8001 100644 --- a/theme.toml +++ b/theme.toml @@ -1,4 +1,4 @@ -name = "Hugo Next" +name = "Hugo NexT" license = "MIT" licenselink = "https://github.com/hugo-next/hugo-theme-next/blob/main/LICENSE" description = "Easily & powerful theme for Hugo engine." From c1e7e596467f0e1748394ccac51546350c46143d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sun, 31 Jul 2022 18:01:57 +0800 Subject: [PATCH 03/29] :wrench: :seedling: Complete the algolia search feature, Close #9. --- .../js/third-party/search/algolia-search.js | 130 ---------------- assets/js/third-party/search/algolia.js | 141 ++++++++++++++++++ .../search/{local-search.js => local.js} | 0 data/resources.yaml | 17 ++- exampleSite/config.yaml | 8 +- layouts/partials/init.html | 15 +- layouts/partials/scripts.html | 10 +- 7 files changed, 182 insertions(+), 139 deletions(-) delete mode 100644 assets/js/third-party/search/algolia-search.js create mode 100644 assets/js/third-party/search/algolia.js rename assets/js/third-party/search/{local-search.js => local.js} (100%) diff --git a/assets/js/third-party/search/algolia-search.js b/assets/js/third-party/search/algolia-search.js deleted file mode 100644 index 12a554c..0000000 --- a/assets/js/third-party/search/algolia-search.js +++ /dev/null @@ -1,130 +0,0 @@ -/* global instantsearch, algoliasearch, CONFIG, pjax */ - -document.addEventListener('DOMContentLoaded', () => { - const { indexName, appID, apiKey, hits } = CONFIG.algolia; - - const search = instantsearch({ - indexName, - searchClient : algoliasearch(appID, apiKey), - searchFunction: helper => { - if (document.querySelector('.search-input').value) { - helper.search(); - } - } - }); - - if (typeof pjax === 'object') { - search.on('render', () => { - pjax.refresh(document.querySelector('.algolia-hits')); - }); - } - - // Registering Widgets - search.addWidgets([ - instantsearch.widgets.configure({ - hitsPerPage: hits.per_page || 10 - }), - - instantsearch.widgets.searchBox({ - container : '.search-input-container', - placeholder : CONFIG.i18n.placeholder, - // Hide default icons of algolia search - showReset : false, - showSubmit : false, - showLoadingIndicator: false, - cssClasses : { - input: 'search-input' - } - }), - - instantsearch.widgets.stats({ - container: '.algolia-stats', - templates: { - text: data => { - const stats = 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: false, - templates : { - item: data => { - const { title, excerpt, excerptStrip, contentStripTruncate } = data._highlightResult; - let result = `${title.value}`; - const content = excerpt || excerptStrip || contentStripTruncate; - if (content && content.value) { - const div = document.createElement('div'); - div.innerHTML = content.value; - result += `

    ${div.textContent.substring(0, 100)}...

    `; - } - return result; - }, - empty: data => { - return `
    - ${CONFIG.i18n.empty.replace('${query}', data.query)} -
    `; - } - }, - cssClasses: { - list: 'search-result-list' - } - }), - - instantsearch.widgets.pagination({ - container: '.algolia-pagination', - scrollTo : false, - showFirst: false, - showLast : false, - 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(); - } - }); -}); diff --git a/assets/js/third-party/search/algolia.js b/assets/js/third-party/search/algolia.js new file mode 100644 index 0000000..1ffb1a0 --- /dev/null +++ b/assets/js/third-party/search/algolia.js @@ -0,0 +1,141 @@ +/* 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(); + } + } + }); + + 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: false, + 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: false, + templates: { + item: data => { + const { title, excerpt, excerptStrip, contentStripTruncate } = data._highlightResult; + let result = `${title.value}`; + const content = excerpt || excerptStrip || contentStripTruncate; + if (content && content.value) { + const div = document.createElement('div'); + div.innerHTML = content.value; + result += `

    ${div.textContent.substring(0, 100)}...

    `; + } + 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: false, + showLast: false, + 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-search.js b/assets/js/third-party/search/local.js similarity index 100% rename from assets/js/third-party/search/local-search.js rename to assets/js/third-party/search/local.js 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 4a3f898..f0d52ce 100644 --- a/exampleSite/config.yaml +++ b/exampleSite/config.yaml @@ -898,15 +898,17 @@ params: # --------------------------------------------------------------- - # TODO - # 内容搜索服务(暂时未实现) + # 内容搜索服务 # Search Services # --------------------------------------------------------------- # Algolia Search # For more information: https://www.algolia.com algoliaSearch: - enable: false + enable: true + appId: # + apiKey: # + indexName: # hits: perPage: 10 diff --git a/layouts/partials/init.html b/layouts/partials/init.html index 34aef75..22f8872 100644 --- a/layouts/partials/init.html +++ b/layouts/partials/init.html @@ -35,7 +35,6 @@ "bookmark" .Site.Params.bookmark "lazyload" .Site.Params.lazyload "motion" .Site.Params.motion - "localSearch" .Site.Params.localSearch "i18n" (dict "placeholder" (T "SearchPh") "empty" (T "SearchEmpty") @@ -44,6 +43,20 @@ ) }} +{{ 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/scripts.html b/layouts/partials/scripts.html index f7ac6dd..4015bd1 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -64,11 +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 }} -{{- $search := resources.Get "js/third-party/search/local-search.js" }} - From 34faa6f6f3a09b7e9657efae767ad73d66789ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sun, 31 Jul 2022 18:21:42 +0800 Subject: [PATCH 04/29] :lipstick: Add algolia logo flag in search result. --- assets/js/third-party/search/algolia.js | 3 +-- static/imgs/algolia-logo.svg | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 static/imgs/algolia-logo.svg diff --git a/assets/js/third-party/search/algolia.js b/assets/js/third-party/search/algolia.js index 1ffb1a0..c929b15 100644 --- a/assets/js/third-party/search/algolia.js +++ b/assets/js/third-party/search/algolia.js @@ -52,8 +52,7 @@ document.addEventListener('DOMContentLoaded', () => { const stats = NexT.CONFIG.i18n.hits_time .replace('${hits}', data.nbHits) .replace('${time}', data.processingTimeMS); - return `${stats}`; - //Algolia`; + return `${stats}Algolia`; } }, cssClasses: { diff --git a/static/imgs/algolia-logo.svg b/static/imgs/algolia-logo.svg new file mode 100644 index 0000000..886c422 --- /dev/null +++ b/static/imgs/algolia-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file From ac844e4e8cfddde2e031525b981f9e1430fcdeb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Mon, 1 Aug 2022 17:14:22 +0800 Subject: [PATCH 05/29] :wrench: Add algolia search indexes content. --- exampleSite/config.yaml | 11 +++++++++-- layouts/_default/list.algoliaindexes.json | 12 ++++++++++++ ...{list.searchindexes.xml => list.localindexes.xml} | 0 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 layouts/_default/list.algoliaindexes.json rename layouts/_default/{list.searchindexes.xml => list.localindexes.xml} (100%) diff --git a/exampleSite/config.yaml b/exampleSite/config.yaml index f0d52ce..43af436 100644 --- a/exampleSite/config.yaml +++ b/exampleSite/config.yaml @@ -68,8 +68,15 @@ outputFormats: # 自定义生成本地搜索文件 # Custom file of indexes for local search SearchIndexes: - mediaType: "application/xml" - baseName: "searchindexes" + mediaType: application/xml + baseName: searchindexes + isPlainText: true + notAlternative: true + # 生成 Algolia 索引文件 + # Build indexes of Aloglia + AlgoliaIndexes: + mediaType: application/json + baseName: algolia isPlainText: true notAlternative: true diff --git a/layouts/_default/list.algoliaindexes.json b/layouts/_default/list.algoliaindexes.json new file mode 100644 index 0000000..909fa6a --- /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": {{ replace .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.searchindexes.xml b/layouts/_default/list.localindexes.xml similarity index 100% rename from layouts/_default/list.searchindexes.xml rename to layouts/_default/list.localindexes.xml From 7ed095d42cc4d0845590d21ca992daa9195c464d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Mon, 1 Aug 2022 17:18:56 +0800 Subject: [PATCH 06/29] :bug: Fixed the aloglia index content . --- layouts/_default/list.algoliaindexes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/_default/list.algoliaindexes.json b/layouts/_default/list.algoliaindexes.json index 909fa6a..91124c1 100644 --- a/layouts/_default/list.algoliaindexes.json +++ b/layouts/_default/list.algoliaindexes.json @@ -4,7 +4,7 @@ { "permalink": "{{ .Permalink | relURL }}", "title": {{ .Title | jsonify }}, - "content": {{ replace .Plain | jsonify }}, + "content": {{ .Plain | jsonify }}, "date": {{ .Date.Format $.Site.Params.timeFormat | jsonify }}, "updated": {{ .Lastmod.Format $.Site.Params.timeFormat | jsonify }} } From 19170556349f863aa9de7eab1a921ad47b6b0aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Tue, 2 Aug 2022 11:22:19 +0800 Subject: [PATCH 07/29] :bug: Fixed the algolia search script find result in content. --- assets/js/third-party/search/algolia.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/js/third-party/search/algolia.js b/assets/js/third-party/search/algolia.js index c929b15..edcd5d6 100644 --- a/assets/js/third-party/search/algolia.js +++ b/assets/js/third-party/search/algolia.js @@ -39,7 +39,7 @@ document.addEventListener('DOMContentLoaded', () => { // Hide default icons of algolia search showReset: false, showSubmit: false, - showLoadingIndicator: false, + showLoadingIndicator: true, cssClasses: { input: 'search-input' } @@ -65,13 +65,13 @@ document.addEventListener('DOMContentLoaded', () => { escapeHTML: false, templates: { item: data => { - const { title, excerpt, excerptStrip, contentStripTruncate } = data._highlightResult; + const { title, excerpt, excerptStrip, content } = data._highlightResult; let result = `${title.value}`; - const content = excerpt || excerptStrip || contentStripTruncate; + const content = excerpt || excerptStrip || content; if (content && content.value) { const div = document.createElement('div'); div.innerHTML = content.value; - result += `

    ${div.textContent.substring(0, 100)}...

    `; + result += `

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

    `; } return result; }, @@ -89,8 +89,8 @@ document.addEventListener('DOMContentLoaded', () => { instantsearch.widgets.pagination({ container: '.algolia-pagination', scrollTo: false, - showFirst: false, - showLast: false, + showFirst: true, + showLast: true, templates: { first: '', last: '', From fdd49ab3cbf345d83d1d8c78620452c98568e4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Tue, 2 Aug 2022 15:12:49 +0800 Subject: [PATCH 08/29] :lipstick: Mark the search result of algolia search. --- .../_common/components/third-party/search.scss | 14 +++++++------- assets/js/third-party/search/algolia.js | 16 ++++++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) 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/js/third-party/search/algolia.js b/assets/js/third-party/search/algolia.js index edcd5d6..dcdb0e7 100644 --- a/assets/js/third-party/search/algolia.js +++ b/assets/js/third-party/search/algolia.js @@ -21,6 +21,10 @@ document.addEventListener('DOMContentLoaded', () => { } }); + const markKeyWords = function(content) { + return content.replaceAll("", ''); + }; + if (typeof pjax === 'object') { search.on('render', () => { pjax.refresh(document.querySelector('.algolia-hits')); @@ -62,16 +66,16 @@ document.addEventListener('DOMContentLoaded', () => { instantsearch.widgets.hits({ container: '.algolia-hits', - escapeHTML: false, + escapeHTML: true, templates: { item: data => { - const { title, excerpt, excerptStrip, content } = data._highlightResult; - let result = `${title.value}`; - const content = excerpt || excerptStrip || content; + 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 = content.value; - result += `

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

    `; + div.innerHTML = markKeyWords(content.value); + result += `

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

    `; } return result; }, From bb70f5b6a50239b89ea1d7e46f98222169da78e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Tue, 2 Aug 2022 18:18:26 +0800 Subject: [PATCH 09/29] :wrench: Try to fixed the Pre in section. --- layouts/partials/post/footer.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/layouts/partials/post/footer.html b/layouts/partials/post/footer.html index 0a88841..0454b27 100644 --- a/layouts/partials/post/footer.html +++ b/layouts/partials/post/footer.html @@ -25,15 +25,15 @@
    {{- with .NextInSection }} - {{- end }}
    {{- with .PrevInSection }} - {{- end }} From 1f668be6fafebab5cac6cd7fa9274c081f959ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Tue, 2 Aug 2022 18:34:55 +0800 Subject: [PATCH 10/29] :bug: Fixed the build error due to about the syntax error --- layouts/partials/post/footer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/post/footer.html b/layouts/partials/post/footer.html index 0454b27..cffa3eb 100644 --- a/layouts/partials/post/footer.html +++ b/layouts/partials/post/footer.html @@ -25,7 +25,7 @@
    {{- with .NextInSection }} - {{- end }} From 97799aaaa89fc5fd5ee8760261ae650b92e4c345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Tue, 2 Aug 2022 18:42:33 +0800 Subject: [PATCH 11/29] :bug: Fixed the archives list page permalink visit. --- layouts/partials/list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/list.html b/layouts/partials/list.html index 5c6f55d..82fd9b0 100644 --- a/layouts/partials/list.html +++ b/layouts/partials/list.html @@ -18,7 +18,7 @@ {{- else }} - {{- end }} From 6cf961d392381484514ae90974006c9684f9d84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Fri, 5 Aug 2022 15:18:52 +0800 Subject: [PATCH 12/29] :lipstick: Implement the special page for friend's links show. Close #26 --- .gitignore | 7 + .../css/_common/components/pages/flinks.scss | 127 ++++++++++++++++++ .../css/_common/components/pages/index.scss | 1 + assets/css/_common/components/post/index.scss | 2 +- .../_common/components/post/post-footer.scss | 2 +- assets/css/_schemes/Gemini/index.scss | 8 +- assets/js/motion.js | 2 +- exampleSite/content/flinks.md | 12 ++ exampleSite/data/flinks.yaml | 29 ++++ layouts/flinks/single.html | 34 +++++ layouts/partials/head/style.html | 2 +- 11 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 assets/css/_common/components/pages/flinks.scss create mode 100644 exampleSite/content/flinks.md create mode 100644 exampleSite/data/flinks.yaml create mode 100644 layouts/flinks/single.html diff --git a/.gitignore b/.gitignore index ac41c2c..7c578ae 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ exampleSite/content/**/ !exampleSite/content/archives !exampleSite/content/post +# Exclude special files in data folder +!exampleSite/data + # Exclude special files in static folder !exampleSite/static @@ -16,3 +19,7 @@ exampleSite/content/**/ !exampleSite/config.yaml !exampleSite/start.sh +data/* +!data/config.yaml +!data/resources.yaml + diff --git a/assets/css/_common/components/pages/flinks.scss b/assets/css/_common/components/pages/flinks.scss new file mode 100644 index 0000000..a9b605e --- /dev/null +++ b/assets/css/_common/components/pages/flinks.scss @@ -0,0 +1,127 @@ +.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 { + 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; + } + + .flinks-item-desc { + padding: 10px 0; + font-size: .92em; + } + + } + } + + .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-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/_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/exampleSite/content/flinks.md b/exampleSite/content/flinks.md new file mode 100644 index 0000000..d90beb4 --- /dev/null +++ b/exampleSite/content/flinks.md @@ -0,0 +1,12 @@ +--- +title: "站点示例" +type: flinks +url: flinks.html +--- + +如想要交换友情链接,请在评论区留下你的站点信息,格式参考如下: + +> **名称:** NexT 主题
    +> **说明:** 保持简单的易用性和强大的功能。
    +> **站标:** https://hugo-next.eu.org/imgs/hugo_next_avatar.png
    +> **网址:** https://hugo-next.eu.org \ No newline at end of file diff --git a/exampleSite/data/flinks.yaml b/exampleSite/data/flinks.yaml new file mode 100644 index 0000000..76bffae --- /dev/null +++ b/exampleSite/data/flinks.yaml @@ -0,0 +1,29 @@ +# 友情链接 +# Friend's links + +- FLinksTitle: 官方示例 + FLinksDesc: 来自主题官方的示例内容。 + FLinksList: + - name: Hugo + desc: 世界上最快的网站建设框架! + image: https://gohugo.io/favicon-32x32.png + link: https://gohugo.io + + - name: Hugo-NexT + desc: Hugo NexT 官方预览网站。 + image: https://hugo-next.eu.org/imgs/hugo_next_avatar.png + link: https://hugo-next.eu.org + + - name: 凡梦星尘空间站 + desc: 再平凡的人也有属于他的梦想! + image: https://lisenhui.cn/img/avatar.png + link: https://lisenhui.cn + + +- FLinksTitle: Hugo NexT 粉丝群体 + FLinksDesc: 来自 Hugo NexT 主题爱好者们的精彩呈现! + FLinksList: + - name: 阿哈吉 + desc: 全网首个 Hugo NexT 忠实粉丝用户 + image: https://a.happy2008.top/imgs/stayhome-small.png + link: https://a.happy2008.top/ \ No newline at end of file diff --git a/layouts/flinks/single.html b/layouts/flinks/single.html new file mode 100644 index 0000000..ea0c330 --- /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/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 }} From 1677648167c7e7f47223da3fe89e649537a5ea41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sat, 6 Aug 2022 15:18:13 +0800 Subject: [PATCH 13/29] :lipstick: Add quote & note shortcodes. Close #29 --- exampleSite/content/post/shortcodes.md | 76 ++++++++++++++++++++++++++ layouts/shortcodes/note.html | 3 + layouts/shortcodes/quote.html | 3 + 3 files changed, 82 insertions(+) create mode 100644 exampleSite/content/post/shortcodes.md create mode 100644 layouts/shortcodes/note.html create mode 100644 layouts/shortcodes/quote.html diff --git a/exampleSite/content/post/shortcodes.md b/exampleSite/content/post/shortcodes.md new file mode 100644 index 0000000..b103e6b --- /dev/null +++ b/exampleSite/content/post/shortcodes.md @@ -0,0 +1,76 @@ +--- +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 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/layouts/shortcodes/note.html b/layouts/shortcodes/note.html new file mode 100644 index 0000000..6f15f99 --- /dev/null +++ b/layouts/shortcodes/note.html @@ -0,0 +1,3 @@ +
    + {{ .Inner | markdownify }} +
    \ No newline at end of file diff --git a/layouts/shortcodes/quote.html b/layouts/shortcodes/quote.html new file mode 100644 index 0000000..eb02719 --- /dev/null +++ b/layouts/shortcodes/quote.html @@ -0,0 +1,3 @@ +
    + {{ .Inner | markdownify }} +
    \ No newline at end of file From 96ba605026a05c60eada2f097f6d5c5d8592f5a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sat, 6 Aug 2022 16:15:15 +0800 Subject: [PATCH 14/29] :bug: Fixed some configuration & display scripts. --- assets/js/next-boot.js | 2 +- exampleSite/config.yaml | 15 ++++++++++----- exampleSite/content/about.md | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) 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/exampleSite/config.yaml b/exampleSite/config.yaml index 43af436..20656b0 100644 --- a/exampleSite/config.yaml +++ b/exampleSite/config.yaml @@ -67,7 +67,7 @@ outputFormats: baseName: "rss" # 自定义生成本地搜索文件 # Custom file of indexes for local search - SearchIndexes: + LocalIndexes: mediaType: application/xml baseName: searchindexes isPlainText: true @@ -81,7 +81,7 @@ outputFormats: notAlternative: true outputs: - home: ["HTML", "RSS", "SearchIndexes"] + home: ["HTML", "RSS", "LocalIndexes"] #-------------------------------------- # 菜单配置说明 @@ -112,16 +112,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 主题参数配置 @@ -912,7 +917,7 @@ params: # Algolia Search # For more information: https://www.algolia.com algoliaSearch: - enable: true + enable: false appId: # apiKey: # indexName: # diff --git a/exampleSite/content/about.md b/exampleSite/content/about.md index ca58c5f..c4e89c7 100644 --- a/exampleSite/content/about.md +++ b/exampleSite/content/about.md @@ -1,6 +1,6 @@ --- title: "关于 Hugo NexT 组织" -description: "" +description: "Hugo NexT 组织介绍说明。" date: 2022-06-09T20:12:52+08:00 lastmod: 2022-06-09T20:12:52+08:00 From 30d161b1e209f0873acf3e680b28104d23e44223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sun, 7 Aug 2022 11:48:05 +0800 Subject: [PATCH 15/29] :lipstick: Fixed the highlight code block margin bottom pixels. --- assets/css/_common/scaffolding/highlight/copy-code.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/css/_common/scaffolding/highlight/copy-code.scss b/assets/css/_common/scaffolding/highlight/copy-code.scss index 63d538c..ee42aa1 100644 --- a/assets/css/_common/scaffolding/highlight/copy-code.scss +++ b/assets/css/_common/scaffolding/highlight/copy-code.scss @@ -2,6 +2,7 @@ .highlight { background: var(--highlight-background); + margin-bottom: 26px; .table-container, pre { position: relative; From aa8a60d852543e4de5f92a795ce9b7ac67c9e6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E6=A2=A6=E6=98=9F=E5=B0=98?= Date: Sun, 7 Aug 2022 16:59:38 +0800 Subject: [PATCH 16/29] :art: Use more standard parameter name which call avatar in flinks page. --- exampleSite/data/flinks.yaml | 8 ++++---- layouts/flinks/single.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/exampleSite/data/flinks.yaml b/exampleSite/data/flinks.yaml index 76bffae..3a43c14 100644 --- a/exampleSite/data/flinks.yaml +++ b/exampleSite/data/flinks.yaml @@ -6,17 +6,17 @@ FLinksList: - name: Hugo desc: 世界上最快的网站建设框架! - image: https://gohugo.io/favicon-32x32.png + avatar: https://gohugo.io/favicon-32x32.png link: https://gohugo.io - name: Hugo-NexT desc: Hugo NexT 官方预览网站。 - image: https://hugo-next.eu.org/imgs/hugo_next_avatar.png + avatar: https://hugo-next.eu.org/imgs/hugo_next_avatar.png link: https://hugo-next.eu.org - name: 凡梦星尘空间站 desc: 再平凡的人也有属于他的梦想! - image: https://lisenhui.cn/img/avatar.png + avatar: https://lisenhui.cn/img/avatar.png link: https://lisenhui.cn @@ -25,5 +25,5 @@ FLinksList: - name: 阿哈吉 desc: 全网首个 Hugo NexT 忠实粉丝用户 - image: https://a.happy2008.top/imgs/stayhome-small.png + avatar: https://a.happy2008.top/imgs/stayhome-small.png link: https://a.happy2008.top/ \ No newline at end of file diff --git a/layouts/flinks/single.html b/layouts/flinks/single.html index ea0c330..cbe325d 100644 --- a/layouts/flinks/single.html +++ b/layouts/flinks/single.html @@ -15,7 +15,7 @@