diff --git a/_config.yml b/_config.yml index 230684a..b7521b0 100755 --- a/_config.yml +++ b/_config.yml @@ -25,10 +25,10 @@ sidebar: # about: '[关于](/about/)' # Sidebar widgets widgets: - index: welcome, recent, timeline # for home/wiki/categories/tags/archives/404 pages + index: welcome, search, recent, timeline # for home/wiki/categories/tags/archives/404 pages page: welcome, toc # for pages using 'layout:page' - post: toc, ghrepo, ghissues # for pages using 'layout:post' - wiki: ghrepo, toc, ghissues, related # for pages using 'layout:wiki' + post: toc, ghrepo, search, ghissues # for pages using 'layout:post' + wiki: search, ghrepo, toc, ghissues, related # for pages using 'layout:wiki' ######## Index ######## post-index: # 近期发布 分类 标签 归档 and ... @@ -61,6 +61,11 @@ article: max_count: 5 +search: + service: local_search # hexo, todo... + local_search: # npm i hexo-generator-search + + ######## Comments ######## comments: service: # beaudar, utterances, twikoo, waline diff --git a/_data/widgets.yml b/_data/widgets.yml index 8d19eb5..29e7ed9 100644 --- a/_data/widgets.yml +++ b/_data/widgets.yml @@ -2,7 +2,10 @@ # layout即组件布局,支持自定义的有: # - markdown: 渲染 md 文本 # - +search: + layout: search + filter: auto # auto or 'path' + ghrepo: layout: ghrepo related: diff --git a/languages/en.yml b/languages/en.yml index adc51da..a5f1333 100755 --- a/languages/en.yml +++ b/languages/en.yml @@ -41,6 +41,11 @@ page: why: The address may be entered incorrectly or the address has been deleted. action: Back to Home +search: + search: Search + search_in: Search in %s + no_results: No Results! + message: copied: Copied! diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml index ce87ae3..49af285 100755 --- a/languages/zh-CN.yml +++ b/languages/zh-CN.yml @@ -41,6 +41,11 @@ page: why: 可能是输入地址有误或该地址已被删除 action: 返回主页 +search: + search: 站内搜索 + search_in: 在 %s 中搜索 + no_results: 没有找到内容! + message: copied: 复制成功 diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml index c874176..f49a3dc 100755 --- a/languages/zh-TW.yml +++ b/languages/zh-TW.yml @@ -41,6 +41,11 @@ page: why: 可能是網址有誤或已經刪除 action: 返回首頁 +search: + search: 站內搜索 + search_in: 在 %s 中搜索 + no_results: 沒有找到內容! + message: copied: 複製成功 diff --git a/layout/_partial/scripts/index.ejs b/layout/_partial/scripts/index.ejs index 3dc91bb..7d848c3 100644 --- a/layout/_partial/scripts/index.ejs +++ b/layout/_partial/scripts/index.ejs @@ -107,6 +107,15 @@ jQuery: '<%- url_for(theme.plugins.jquery || "https://fastly.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js") %>' }; + if ('<%- theme.search.service %>') { + stellar.search = {}; + stellar.search.service = '<%- theme.search.service %>'; + if (stellar.search.service == 'local_search') { + let service_obj = Object.assign({}, <%- JSON.stringify(config.search) %>); + stellar.search[stellar.search.service] = service_obj; + } + } + // stellar js stellar.plugins.stellar = Object.assign(<%- JSON.stringify(theme.plugins.stellar) %>); diff --git a/layout/_partial/widgets/search.ejs b/layout/_partial/widgets/search.ejs new file mode 100644 index 0000000..438f5ef --- /dev/null +++ b/layout/_partial/widgets/search.ejs @@ -0,0 +1,31 @@ +<% +function layoutDiv() { + var el = '' + el += '' + el += '' + el += '' + var filter = '' + if (item.filter == 'auto' && page.layout == 'wiki') { + let matches = page.path.match(/(.*?)\/(.*?)\//i) + if (matches?.length > 0) { + filter = matches[0] + } + } + el += ' 0) { + filter = '/' + filter + el += ' data-filter="' + filter + '"' + el += ' placeholder="' + (item.placeholder || __('search.search_in', filter)) + '">' + } else { + el += ' placeholder="' + (item.placeholder || __('search.search')) + '">' + } + el += '' + el += '' + el += '' + __('search.no_results') + '' + el += '' + el += '' + el += '' + return el +} +%> +<%- layoutDiv() %> diff --git a/source/css/_layout/widgets/search.styl b/source/css/_layout/widgets/search.styl new file mode 100644 index 0000000..a6109b0 --- /dev/null +++ b/source/css/_layout/widgets/search.styl @@ -0,0 +1,3 @@ +.widgets .widget-wrapper.search + margin-top: 0 + margin-bottom: 0 diff --git a/source/css/_layout/widgets/widgets.styl b/source/css/_layout/widgets/widgets.styl index 41a2c77..ba4f9ce 100644 --- a/source/css/_layout/widgets/widgets.styl +++ b/source/css/_layout/widgets/widgets.styl @@ -10,8 +10,6 @@ z-index: 1 line-height: 1.2 .widget-wrapper - display: block - margin: 1rem 0 2rem .widget-header padding-left: var(--gap-l) padding-right: var(--gap-l) @@ -56,3 +54,7 @@ margin-top: 3rem .widget-wrapper+.widget-wrapper.toc .widget-header margin-top: 1rem + +.widget-wrapper + display: block + margin: 1rem 0 2rem \ No newline at end of file diff --git a/source/css/_plugins/index.styl b/source/css/_plugins/index.styl index 2a68111..c8db7cc 100644 --- a/source/css/_plugins/index.styl +++ b/source/css/_plugins/index.styl @@ -8,6 +8,10 @@ if hexo-config('plugins.scrollreveal.enable') if hexo-config('plugins.fancybox.enable') @import 'fancybox' +// 搜索 +if hexo-config('search.service') == 'local_search' + @import 'search/local-search' + // 评论 if hexo-config('comments.service') == 'beaudar' @import 'comments/beaudar' diff --git a/source/css/_plugins/search/local-search.styl b/source/css/_plugins/search/local-search.styl new file mode 100644 index 0000000..96e5685 --- /dev/null +++ b/source/css/_plugins/search/local-search.styl @@ -0,0 +1,70 @@ +.search-wrapper + width: 100% + >.search-form + position: sticky + top: 1rem + .search-input + width: 100% + padding: 0.75rem 1rem + line-height: 1 + box-sizing: border-box + border-radius: $border-block + background-color: var(--card) + color: var(--text-p0) + box-shadow: $boxshadow-button + trans1 box-shadow + &:hover + box-shadow: 0 0 2px 0px alpha($color-theme, 0.2), 0 0 8px 0px alpha($color-theme, 0.2) + &:focus + box-shadow: 0 0 2px 0px alpha($color-theme, 0.4), 0 0 8px 0px alpha($color-theme, 0.4) + + .search-no-result + display: none + margin: 1em auto + color: var(--text-p1) + text-align: center + font-size: $fs-14 + padding: 2rem + background: var(--block) + border-radius: $border-block + + #search-result + ul.search-result-list + padding: 0 + margin: 0 + list-style-type: none + li + margin: 1em auto + &:hover + .search-result-title + color: $color-hover + .search-result-title + background-image: none + color: var(--text-p1) + text-transform: capitalize + font-weight: bold + line-height: 1.2 + + .search-result-content + overflow: hidden + color: var(--text-p3) + margin: .4em auto + max-height: 13em + text-align: justify + font-size: $fs-12 + line-height: 1.2 + display: -webkit-box + -webkit-box-orient: vertical + overflow: hidden + -webkit-line-clamp: 3 + + .search-keyword + border-bottom: 1px dashed $color-hover + color: $color-hover + font-weight: bold + + + +.search-wrapper.noresult + .search-no-result + display: block \ No newline at end of file diff --git a/source/js/main.js b/source/js/main.js index f88f443..da3f3da 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -301,6 +301,39 @@ if (stellar.plugins.fancybox) { } } + +if (stellar.search.service) { + if (stellar.search.service == 'local_search') { + stellar.jQuery(() => { + stellar.loadScript('/js/search/local-search.js', { defer: true }).then(function () { + var $inputArea = $("input#search-input"); + var $resultArea = document.querySelector("div#search-result"); + $inputArea.focus(function() { + var path = stellar.search[stellar.search.service]?.path || '/search.xml'; + const filter = $inputArea.attr('data-filter') || ''; + searchFunc(path, filter, 'search-input', 'search-result'); + }); + $inputArea.keydown(function(e) { + if (e.which == 13) { + e.preventDefault(); + } + }); + var observer = new MutationObserver(function(mutationsList, observer) { + if (mutationsList.length == 1) { + if (mutationsList[0].addedNodes.length) { + $('.search-wrapper').removeClass('noresult'); + } else if (mutationsList[0].removedNodes.length) { + $('.search-wrapper').addClass('noresult'); + } + } + }); + observer.observe($resultArea, { childList: true }); + }); + }) + } +} + + // heti if (stellar.plugins.heti) { stellar.loadCSS(stellar.plugins.heti.css); diff --git a/source/js/search/local-search.js b/source/js/search/local-search.js new file mode 100644 index 0000000..0a32acd --- /dev/null +++ b/source/js/search/local-search.js @@ -0,0 +1,161 @@ +// A local search script with the help of +// [hexo-generator-search](https://github.com/PaicHyperionDev/hexo-generator-search) +// Copyright (C) 2015 +// Joseph Pan +// Shuhao Mao +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA +// +// Modified by: +// Pieter Robberechts + +/*exported searchFunc*/ +var searchFunc = function(path, filter, searchId, contentId) { + + function stripHtml(html) { + html = html.replace(/