diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 1deada7..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - - - - - - -## I want to create a Bug report - - - -- [] Yes, I have read [Hexo Docs page](https://hexo.io/docs/), especially [Templates](https://hexo.io/docs/templates.html), [Variables](https://hexo.io/docs/variables.html), [Helpers](https://hexo.io/docs/helpers.html) and [Troubleshooting](https://hexo.io/docs/troubleshooting.html). -- [] Yes, I have read [Butterfly Documentation](https://butterfly.js.org/posts/21cfbf15/). -- [] And yes, I already searched for current [issues](https://github.com/jerryc127/hexo-theme-butterfly/issues?utf8=%E2%9C%93&q=is%3Aissue) and this did not help me. - -## Butterfly Information - - - -**Butterfly Version:** - - -**Platform:** - - -**Browser:** - -## Expected behavior - -## Actual behavior - -## Steps to reproduce the behavior -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - - - -## Screenshots - - -## Website - -## Describe the bug diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..10fd0bb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,63 @@ +name: Bug report +description: Create a report to help us improve +title: '[Bug]: ' + +body: + - type: markdown + attributes: + value: | + 重要:請依照該模板來提交 + Please follow the template to create a new issue + - type: input + id: butterfly-ver + attributes: + label: 使用的 Butterfly 版本? | What version of Butterfly are you use? + description: 檢視主題的 package.json | Check the theme's package.json + validations: + required: true + + - type: dropdown + id: browser + attributes: + label: 使用的瀏覽器? || What browse are you using? + options: + - Chrome + - Edge + - Safari + - Opera + - Other + validations: + required: true + + - type: dropdown + id: platform + attributes: + label: 使用的系統? || What operating system are you using? + options: + - Windows + - macOS + - Linux + - Android + - iOS + - Other + validations: + required: true + + - type: textarea + id: description + attributes: + label: 問題描述 | Describe the bug + description: 請描述你的問題現象 | A clear and concise description of what the bug is. + placeholder: 請儘量提供截圖來定位問題 | If applicable, add screenshots to help explain your problem + value: + validations: + required: true + + - type: input + id: website + attributes: + label: 出現問題網站 | Website + description: 請提供下可復現網站地址 | Please supply a website url which can reproduce problem. + placeholder: + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..9b338d0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,22 @@ +blank_issues_enabled: false +contact_links: + - name: Questions about Butterfly + url: https://github.com/jerryc127/hexo-theme-butterfly/discussions + about: 一些使用問題請到 Discussion 詢問。 Please ask questions in Discussion. + + - name: Butterfly Q&A + url: https://butterfly.js.org/posts/98d20436/ + about: Butterfly Q&A + + - name: Telegram + url: https://t.me/bu2fly + about: 'Official Telegram Group' + + - name: QQ 1群 + url: https://jq.qq.com/?_wv=1027&k=KU9105XR + about: '群號 1070540070,不要兩個Q群都添加' + + - name: QQ 2群 + url: https://jq.qq.com/?_wv=1027&k=r1nK0DQz + about: '群號 978221020,不要兩個Q群都添加' + diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 4842758..0000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: Custom issue template -about: Describe this issue template's purpose here. -title: '' -labels: '' -assignees: '' ---- - - diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..3bf7c30 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,14 @@ +name: Feature request +description: Suggest an idea for this project +title: '[Feature]: ' + +body: + - type: textarea + id: feature-request + attributes: + label: 想要的功能 | What feature do you want? + description: 請描述你需要的新功能 | A clear and concise description of what the feature is. + placeholder: + value: + validations: + require: true \ No newline at end of file diff --git a/.github/stale.yml b/.github/stale.yml index 2d74a9c..ff7578d 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -10,7 +10,7 @@ exemptLabels: - enhancement - documentation # Label to use when marking an issue as stale -staleLabel: wontfix +staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had diff --git a/_config.yml b/_config.yml index 96bbe9a..299f671 100644 --- a/_config.yml +++ b/_config.yml @@ -39,6 +39,7 @@ social: # fas fa-envelope: mailto:xxxxxx@gmail.com || Email # search (搜索) +# see https://butterfly.js.org/posts/ceeb73f/#搜索系統 # -------------------------------------- # Algolia search @@ -50,6 +51,8 @@ algolia_search: # Local search local_search: enable: false + preload: false + CDN: # Math (數學) # -------------------------------------- @@ -148,6 +151,7 @@ post_meta: label: true # true or false 顯示描述性文字 # wordcount (字數統計) +# see https://butterfly.js.org/posts/ceeb73f/#字數統計 wordcount: enable: false post_wordcount: true @@ -181,6 +185,7 @@ toc: post_copyright: enable: true decode: false + author_href: license: CC BY-NC-SA 4.0 license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/ @@ -308,7 +313,7 @@ valine: waline: serverURL: # Waline server address url bg: # waline background - visitor: false + pageview: false option: # utterances @@ -468,6 +473,8 @@ site_verification: # blockquote_padding_color: "#49b1f5" # blockquote_background_color: "#49b1f5" # scrollbar_color: "#49b1f5" +# meta_theme_color_light: "ffffff" +# meta_theme_color_dark: "#0d0d0d" # The top_img settings of home page # default: top img - full screen, site info - middle (默認top_img全屏,site_info在中間) @@ -614,6 +621,7 @@ aside: button: true mobile: true # display on mobile position: right # left or right + archives: true card_author: enable: true description: @@ -827,88 +835,62 @@ inject: # Don't modify the following settings unless you know how they work # 非必要請不要修改 CDN: - # main - main_css: - main: - utils: - - # pjax - pjax: - - # comments - gitalk: - gitalk_css: - blueimp_md5: - valine: - disqusjs: - disqusjs_css: - utterances: - twikoo: - waline: - giscus: - - # share - addtoany: - sharejs: - sharejs_css: - - # search - local_search: - algolia_js: - algolia_search_v4: - instantsearch_v4: - - # math - mathjax: - katex: - katex_copytex: - katex_copytex_css: - mermaid: - - # count - busuanzi: - - # background effect - canvas_ribbon: - canvas_fluttering_ribbon: - canvas_nest: - - lazyload: - instantpage: - typed: - pangu: - - # photo - fancybox_css_v4: - fancybox_v4: - medium_zoom: - - # snackbar - snackbar_css: - snackbar: - - # effect - activate_power_mode: - fireworks: - click_heart: - ClickShowText: - - # fontawesome - fontawesomeV6: - - # Conversion between Traditional and Simplified Chinese - translate: - - # flickr-justified-gallery - flickr_justified_gallery_js: - flickr_justified_gallery_css: - - # aplayer - aplayer_css: - aplayer_js: - meting_js: - - # Prism.js - prismjs_js: - prismjs_lineNumber_js: - prismjs_autoloader: \ No newline at end of file + # The CDN provider of internal scripts (主題內部 js 的 cdn 配置) + # option: local/jsdelivr + # Dev version cannot choose jsdelivr (dev版的主題不能設置為 jsdelivr) + internal_provider: local + # The CDN provider of third party scripts (第三方 js 的 cdn 配置) + # option: local/jsdelivr + # when set it to local, you need to install hexo-butterfly-extjs + third_party_provider: jsdelivr + option: + # main_css: + # main: + # utils: + # translate: + # local_search: + # algolia_js: + # algolia_search_v4: + # instantsearch_v4: + # pjax: + # gitalk: + # gitalk_css: + # blueimp_md5: + # valine: + # disqusjs: + # disqusjs_css: + # twikoo: + # waline_js: + # waline_css: + # sharejs: + # sharejs_css: + # mathjax: + # katex: + # katex_copytex: + # katex_copytex_css: + # mermaid: + # canvas_ribbon: + # canvas_fluttering_ribbon: + # canvas_nest: + # lazyload: + # instantpage: + # typed: + # pangu: + # fancybox_css_v4: + # fancybox_v4: + # medium_zoom: + # snackbar_css: + # snackbar: + # activate_power_mode: + # fireworks: + # click_heart: + # ClickShowText: + # fontawesomeV6: + # flickr_justified_gallery_js: + # flickr_justified_gallery_css: + # aplayer_css: + # aplayer_js: + # meting_js: + # prismjs_js: + # prismjs_lineNumber_js: + # prismjs_autoloader: \ No newline at end of file diff --git a/languages/default.yml b/languages/default.yml index 2b2a551..833fb6c 100644 --- a/languages/default.yml +++ b/languages/default.yml @@ -43,7 +43,6 @@ search: hits_stats: '${hits} results found in ${time} ms' local_search: - label: Local search input_placeholder: Search for Posts hits_empty: "We didn't find any results for the search: ${query}" diff --git a/languages/en.yml b/languages/en.yml index 323d9f4..9d303e0 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -43,7 +43,6 @@ search: hits_stats: '${hits} results found in ${time} ms' local_search: - label: Local search input_placeholder: Search for Posts hits_empty: "We didn't find any results for the search: ${query}" diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml index db3d2b9..55900d2 100644 --- a/languages/zh-CN.yml +++ b/languages/zh-CN.yml @@ -44,7 +44,6 @@ search: hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' local_search: - label: 本地搜索 input_placeholder: 搜索文章 hits_empty: '找不到您查询的内容:${query}' diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml index 81a3615..61d667f 100644 --- a/languages/zh-TW.yml +++ b/languages/zh-TW.yml @@ -44,7 +44,6 @@ search: hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' local_search: - label: 本地搜尋 input_placeholder: 搜尋文章 hits_empty: '找不到您查詢的內容:${query}' diff --git a/layout/includes/additional-js.pug b/layout/includes/additional-js.pug index 79fc8b4..7d1e93e 100644 --- a/layout/includes/additional-js.pug +++ b/layout/includes/additional-js.pug @@ -1,34 +1,34 @@ div - script(src=url_for(theme.CDN.utils)) - script(src=url_for(theme.CDN.main)) + script(src=url_for(theme.asset.utils)) + script(src=url_for(theme.asset.main)) if theme.translate.enable - script(src=url_for(theme.CDN.translate)) + script(src=url_for(theme.asset.translate)) if theme.medium_zoom - script(src=url_for(theme.CDN.medium_zoom)) + script(src=url_for(theme.asset.medium_zoom)) else if theme.fancybox - script(src=url_for(theme.CDN.fancybox_v4)) + script(src=url_for(theme.asset.fancybox_v4)) if theme.instantpage - script(src=url_for(theme.CDN.instantpage), type='module') + script(src=url_for(theme.asset.instantpage), type='module') if theme.lazyload.enable - script(src=url_for(theme.CDN.lazyload)) + script(src=url_for(theme.asset.lazyload)) if theme.snackbar.enable - script(src=url_for(theme.CDN.snackbar)) + script(src=url_for(theme.asset.snackbar)) if theme.pangu.enable != partial("includes/third-party/pangu.pug", {}, { cache: true }) //- search if theme.algolia_search.enable - script(src=url_for(theme.CDN.algolia_search_v4)) - script(src=url_for(theme.CDN.instantsearch_v4)) - script(src=url_for(theme.CDN.algolia_js)) + script(src=url_for(theme.asset.algolia_search_v4)) + script(src=url_for(theme.asset.instantsearch_v4)) + script(src=url_for(theme.asset.algolia_js)) else if theme.local_search.enable - script(src=url_for(theme.CDN.local_search)) + script(src=url_for(theme.asset.local_search)) if theme.preloader != partial("includes/loading/loading-js", {}, { cache: true }) @@ -69,4 +69,4 @@ div != partial("includes/third-party/pjax", {}, { cache: true }) if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv - script(async data-pjax src=url_for(theme.CDN.busuanzi)) + script(async data-pjax src='//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js') diff --git a/layout/includes/head.pug b/layout/includes/head.pug index 748684c..3f9e95b 100644 --- a/layout/includes/head.pug +++ b/layout/includes/head.pug @@ -16,7 +16,9 @@ - else pageKeywords = Array.isArray(config.keywords) ? (config.keywords).join(','): ([]).join(',') || config.keywords - var pageAuthor = config.email ? config.author + ',' + config.email : config.author - var pageCopyright = config.copyright || config.author -- var themeColor = theme.display_mode === 'dark' ? '#0d0d0d' : '#ffffff' +- var themeColorLight = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_light || '#ffffff' +- var themeColorDark = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_dark || '#0d0d0d' +- var themeColor = theme.display_mode === 'dark' ? themeColorDark : themeColorLight meta(charset='UTF-8') meta(http-equiv="X-UA-Compatible" content="IE=edge") @@ -46,14 +48,14 @@ if (theme.pwa && theme.pwa.enable) !=partial('includes/head/pwa', {}, {cache: true}) //- main css -link(rel='stylesheet', href=url_for(theme.CDN.main_css)) -link(rel='stylesheet', href=url_for(theme.CDN.fontawesomeV6) media="print" onload="this.media='all'") +link(rel='stylesheet', href=url_for(theme.asset.main_css)) +link(rel='stylesheet', href=url_for(theme.asset.fontawesomeV6) media="print" onload="this.media='all'") if (theme.snackbar && theme.snackbar.enable) - link(rel='stylesheet', href=url_for(theme.CDN.snackbar_css) media="print" onload="this.media='all'") + link(rel='stylesheet', href=url_for(theme.asset.snackbar_css) media="print" onload="this.media='all'") if theme.fancybox - link(rel='stylesheet' href=url_for(theme.CDN.fancybox_css_v4) media="print" onload="this.media='all'") + link(rel='stylesheet' href=url_for(theme.asset.fancybox_css_v4) media="print" onload="this.media='all'") //- google_adsense !=partial('includes/head/google_adsense', {}, {cache: true}) diff --git a/layout/includes/head/config.pug b/layout/includes/head/config.pug index 49fe4fe..61f62d0 100644 --- a/layout/includes/head/config.pug +++ b/layout/includes/head/config.pug @@ -19,7 +19,8 @@ let localSearch = 'undefined'; if (theme.local_search && theme.local_search.enable) { localSearch = JSON.stringify({ - path: config.search.path, + path: theme.local_search.CDN ? theme.local_search.CDN : config.root + config.search.path, + preload: theme.local_search.preload, languages: { // search languages hits_empty: _p("search.local_search.hits_empty"), @@ -113,8 +114,8 @@ script. Snackbar: !{Snackbar}, source: { justifiedGallery: { - js: '!{url_for(theme.CDN.flickr_justified_gallery_js)}', - css: '!{url_for(theme.CDN.flickr_justified_gallery_css)}' + js: '!{url_for(theme.asset.flickr_justified_gallery_js)}', + css: '!{url_for(theme.asset.flickr_justified_gallery_css)}' } }, isPhotoFigcaption: !{theme.photofigcaption}, diff --git a/layout/includes/header/post-info.pug b/layout/includes/header/post-info.pug index 61b2e7b..3293697 100644 --- a/layout/includes/header/post-info.pug +++ b/layout/includes/header/post-info.pug @@ -61,16 +61,24 @@ if block block - if theme.busuanzi.page_pv + - const commentUse = comments.use + if commentUse && !comments.lazyload + case commentUse[0] + when 'Valine' + if theme.valine.visitor + +pvBlock(url_for(page.path),'leancloud_visitors',page.title) + span.leancloud-visitors-count + when 'Waline' + if theme.waline.pageview + +pvBlock('','','') + span.waline-pageview-count(data-path=url_for(page.path)) + when 'Twikoo' + if theme.twikoo.visitor + +pvBlock('','','') + span#twikoo_visitors + else if theme.busuanzi.page_pv +pvBlock('','post-meta-pv-cv','') span#busuanzi_value_page_pv - else if comments.use && !comments.lazyload - if (comments.use.includes('Valine') && theme.valine.visitor) || (comments.use.includes('Waline') && theme.waline.visitor) - +pvBlock(url_for(page.path),'leancloud_visitors',page.title) - span.leancloud-visitors-count - else if (comments.use.includes('Twikoo') && theme.twikoo.visitor) - +pvBlock('','','') - span#twikoo_visitors if comments.count && !comments.lazyload && page.comments !== false && comments.use - var whichCount = comments.use[0] @@ -96,7 +104,7 @@ when 'Waline' +countBlock a(href=url_for(page.path) + '#post-comment') - span.waline-comment-count(id=url_for(page.path)) + span.waline-comment-count(data-path=url_for(page.path)) when 'Gitalk' +countBlock a(href=url_for(page.path) + '#post-comment') diff --git a/layout/includes/layout.pug b/layout/includes/layout.pug index 5245cce..aabce94 100644 --- a/layout/includes/layout.pug +++ b/layout/includes/layout.pug @@ -1,4 +1,5 @@ - var htmlClassHideAside = theme.aside.enable && theme.aside.hide ? 'hide-aside' : '' +- page.aside = is_archive() ? theme.aside.archives : page.aside - var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : '' - var pageType = is_post() ? 'post' : 'page' diff --git a/layout/includes/post/post-copyright.pug b/layout/includes/post/post-copyright.pug index dfa346d..8c7ca03 100644 --- a/layout/includes/post/post-copyright.pug +++ b/layout/includes/post/post-copyright.pug @@ -1,8 +1,8 @@ if theme.post_copyright.enable && page.copyright !== false - - let author = page.copyright_author ? page.copyright_author : config.author - - let authorHref = page.copyright_author_href ? page.copyright_author_href : `mailto:${config.email}` - - let url = page.copyright_url ? page.copyright_url : page.permalink - - let info = page.copyright_info ? page.copyright_info : _p('post.copyright.copyright_content', theme.post_copyright.license_url, theme.post_copyright.license, config.url, config.title) + - let author = page.copyright_author || config.author + - let authorHref = page.copyright_author_href || theme.post_copyright.author_href || config.url + - let url = page.copyright_url || page.permalink + - let info = page.copyright_info || _p('post.copyright.copyright_content', theme.post_copyright.license_url, theme.post_copyright.license, config.url, config.title) .post-copyright .post-copyright__author span.post-copyright-meta= _p('post.copyright.author') + ": " diff --git a/layout/includes/sidebar.pug b/layout/includes/sidebar.pug index 45a97ee..11bddf8 100644 --- a/layout/includes/sidebar.pug +++ b/layout/includes/sidebar.pug @@ -3,21 +3,16 @@ #sidebar-menus .avatar-img.is-center img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar") - .site-data.is-center - .data-item - a(href=url_for(config.archive_dir) + '/') - .headline= _p('aside.articles') - .length-num= site.posts.length - - .data-item - a(href=url_for(config.tag_dir) + '/' ) - .headline= _p('aside.tags') - .length-num= site.tags.length - - .data-item - a(href=url_for(config.category_dir) + '/') - .headline= _p('aside.categories') - .length-num= site.categories.length + .sidebar-site-data.site-data.is-center + a(href=url_for(config.archive_dir) + '/') + .headline= _p('aside.articles') + .length-num= site.posts.length + a(href=url_for(config.tag_dir) + '/' ) + .headline= _p('aside.tags') + .length-num= site.tags.length + a(href=url_for(config.category_dir) + '/') + .headline= _p('aside.categories') + .length-num= site.categories.length hr !=partial('includes/header/menu_item', {}, {cache: true}) diff --git a/layout/includes/third-party/aplayer.pug b/layout/includes/third-party/aplayer.pug index dd7af2f..c439c4c 100644 --- a/layout/includes/third-party/aplayer.pug +++ b/layout/includes/third-party/aplayer.pug @@ -1,3 +1,3 @@ -link(rel='stylesheet' href=url_for(theme.CDN.aplayer_css) media="print" onload="this.media='all'") -script(src=url_for(theme.CDN.aplayer_js)) -script(src=url_for(theme.CDN.meting_js)) \ No newline at end of file +link(rel='stylesheet' href=url_for(theme.asset.aplayer_css) media="print" onload="this.media='all'") +script(src=url_for(theme.asset.aplayer_js)) +script(src=url_for(theme.asset.meting_js)) \ No newline at end of file diff --git a/layout/includes/third-party/card-post-count/twikoo.pug b/layout/includes/third-party/card-post-count/twikoo.pug index 46ae7c9..68ab35b 100644 --- a/layout/includes/third-party/card-post-count/twikoo.pug +++ b/layout/includes/third-party/card-post-count/twikoo.pug @@ -28,7 +28,7 @@ script. if (typeof twikoo === 'object') { runTwikoo() } else { - getScript('!{theme.CDN.twikoo}').then(runTwikoo) + getScript('!{theme.asset.twikoo}').then(runTwikoo) } } diff --git a/layout/includes/third-party/card-post-count/valine.pug b/layout/includes/third-party/card-post-count/valine.pug index 399151f..2d422fd 100644 --- a/layout/includes/third-party/card-post-count/valine.pug +++ b/layout/includes/third-party/card-post-count/valine.pug @@ -12,7 +12,7 @@ script. } if (typeof Valine === 'function') initValine() - else getScript('!{url_for(theme.CDN.valine)}').then(initValine) + else getScript('!{url_for(theme.asset.valine)}').then(initValine) } window.pjax ? loadValine() : window.addEventListener('load', loadValine) diff --git a/layout/includes/third-party/card-post-count/waline.pug b/layout/includes/third-party/card-post-count/waline.pug index 7090c35..c43a18d 100644 --- a/layout/includes/third-party/card-post-count/waline.pug +++ b/layout/includes/third-party/card-post-count/waline.pug @@ -5,12 +5,13 @@ script. let initData = { el: null, serverURL: '!{theme.waline.serverURL}', + comment: true } - const waline = new Waline(initData) + const waline = Waline.init(initData) } if (typeof Waline === 'function') initWaline() - else getScript('!{url_for(theme.CDN.waline)}').then(initWaline) + else getScript('!{url_for(theme.asset.waline_js)}').then(initWaline) } window.pjax ? loadWaline() : window.addEventListener('load', loadWaline) diff --git a/layout/includes/third-party/comments/disqusjs.pug b/layout/includes/third-party/comments/disqusjs.pug index 268c16f..344be55 100644 --- a/layout/includes/third-party/comments/disqusjs.pug +++ b/layout/includes/third-party/comments/disqusjs.pug @@ -5,7 +5,7 @@ script. function addDisqusjsCSS () { const ele = document.createElement('link') ele.rel = 'stylesheet' - ele.href= '!{url_for(theme.CDN.disqusjs_css)}' + ele.href= '!{url_for(theme.asset.disqusjs_css)}' document.getElementsByTagName('head')[0].appendChild(ele) } @@ -26,7 +26,7 @@ script. if (window.disqusJsLoad) initDisqusjs() else { addDisqusjsCSS() - getScript('!{url_for(theme.CDN.disqusjs)}').then(initDisqusjs) + getScript('!{url_for(theme.asset.disqusjs)}').then(initDisqusjs) window.disqusJsLoad = true } } diff --git a/layout/includes/third-party/comments/facebook_comments.pug b/layout/includes/third-party/comments/facebook_comments.pug index c1ae68d..64879b0 100644 --- a/layout/includes/third-party/comments/facebook_comments.pug +++ b/layout/includes/third-party/comments/facebook_comments.pug @@ -7,7 +7,7 @@ script. if (typeof FB === 'object') FB.XFBML.parse() else { let ele = document.createElement('script') - ele.setAttribute('src','https://connect.facebook.net/!{theme.facebook_comments.lang}/sdk.js#xfbml=1&version=v13.0&autoLogAppEvents=1') + ele.setAttribute('src','https://connect.facebook.net/!{theme.facebook_comments.lang}/sdk.js#xfbml=1&version=v13.0&appId=!{theme.facebook_comments.app_id}&autoLogAppEvents=1') ele.setAttribute('async', 'true') ele.setAttribute('defer', 'true') ele.setAttribute('crossorigin', 'anonymous') diff --git a/layout/includes/third-party/comments/giscus.pug b/layout/includes/third-party/comments/giscus.pug index b09bf5a..df19568 100644 --- a/layout/includes/third-party/comments/giscus.pug +++ b/layout/includes/third-party/comments/giscus.pug @@ -5,7 +5,7 @@ script. let nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{themes.dark}' : '!{themes.light}' const config = Object.assign({ - src: '!{theme.CDN.giscus}', + src: 'https://giscus.app/client.js', 'data-repo': '!{repo}', 'data-repo-id': '!{repo_id}', 'data-category-id': '!{category_id}', diff --git a/layout/includes/third-party/comments/gitalk.pug b/layout/includes/third-party/comments/gitalk.pug index 06ecfd9..fccb64d 100644 --- a/layout/includes/third-party/comments/gitalk.pug +++ b/layout/includes/third-party/comments/gitalk.pug @@ -2,7 +2,7 @@ script. function addGitalkSource () { const ele = document.createElement('link') ele.rel = 'stylesheet' - ele.href= '!{url_for(theme.CDN.gitalk_css)}' + ele.href= '!{url_for(theme.asset.gitalk_css)}' document.getElementsByTagName('head')[0].appendChild(ele) } @@ -24,7 +24,7 @@ script. if (typeof Gitalk === 'function') initGitalk() else { addGitalkSource() - getScript('!{url_for(theme.CDN.gitalk)}').then(initGitalk) + getScript('!{url_for(theme.asset.gitalk)}').then(initGitalk) } } diff --git a/layout/includes/third-party/comments/twikoo.pug b/layout/includes/third-party/comments/twikoo.pug index d7a8831..386ab3f 100644 --- a/layout/includes/third-party/comments/twikoo.pug +++ b/layout/includes/third-party/comments/twikoo.pug @@ -9,7 +9,7 @@ script. envId: '!{envId}', region: '!{region}', onCommentLoaded: function () { - btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.vemoji)')) + btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)')) } }, !{JSON.stringify(option)})) } @@ -37,7 +37,7 @@ script. setTimeout(runFn,0) return } - getScript('!{theme.CDN.twikoo}').then(runFn) + getScript('!{theme.asset.twikoo}').then(runFn) } if ('!{use[0]}' === 'Twikoo' || !!{lazyload}) { diff --git a/layout/includes/third-party/comments/utterances.pug b/layout/includes/third-party/comments/utterances.pug index 25cccf2..7f61831 100644 --- a/layout/includes/third-party/comments/utterances.pug +++ b/layout/includes/third-party/comments/utterances.pug @@ -2,7 +2,7 @@ script. function loadUtterances () { let ele = document.createElement('script') ele.setAttribute('id', 'utterances_comment') - ele.setAttribute('src', '!{url_for(theme.CDN.utterances)}') + ele.setAttribute('src', 'https://utteranc.es/client.js') ele.setAttribute('repo', '!{theme.utterances.repo}') ele.setAttribute('issue-term', '!{theme.utterances.issue_term}') let nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{theme.utterances.dark_theme}' : '#{theme.utterances.light_theme}' diff --git a/layout/includes/third-party/comments/valine.pug b/layout/includes/third-party/comments/valine.pug index 91b3110..025849e 100644 --- a/layout/includes/third-party/comments/valine.pug +++ b/layout/includes/third-party/comments/valine.pug @@ -18,7 +18,7 @@ script. } if (typeof Valine === 'function') initValine() - else getScript('!{url_for(theme.CDN.valine)}').then(initValine) + else getScript('!{url_for(theme.asset.valine)}').then(initValine) } if ('!{theme.comments.use[0]}' === 'Valine' || !!{theme.comments.lazyload}) { diff --git a/layout/includes/third-party/comments/waline.pug b/layout/includes/third-party/comments/waline.pug index cfd05c2..06e8078 100644 --- a/layout/includes/third-party/comments/waline.pug +++ b/layout/includes/third-party/comments/waline.pug @@ -1,23 +1,35 @@ -- const { serverURL, visitor, option } = theme.waline +- const { serverURL, option, pageview } = theme.waline +- const { lazyload, count, use } = theme.comments script. function loadWaline () { + function insertCSS () { + const link = document.createElement("link") + link.rel = "stylesheet" + link.href = "!{url_for(theme.asset.waline_css)}" + document.head.appendChild(link) + } + function initWaline () { - const waline = new Waline(Object.assign({ + const waline = Waline.init(Object.assign({ el: '#waline-wrap', serverURL: '!{serverURL}', - path: location.pathname, - visitor: !{visitor}, - dark: 'html[data-theme="dark"]' + pageview: !{lazyload ? false : pageview}, + dark: 'html[data-theme="dark"]', + path: window.location.pathname, + comment: !{lazyload ? false : count}, }, !{JSON.stringify(option)})) } if (typeof Waline === 'function') initWaline() - else getScript('!{url_for(theme.CDN.waline)}').then(initWaline) + else { + insertCSS() + getScript('!{url_for(theme.asset.waline_js)}').then(initWaline) + } } - if ('!{theme.comments.use[0]}' === 'Waline' || !!{theme.comments.lazyload}) { - if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('waline-wrap'),loadWaline) + if ('!{use[0]}' === 'Waline' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('waline-wrap'),loadWaline) else setTimeout(loadWaline, 0) } else { function loadOtherComment () { diff --git a/layout/includes/third-party/effect.pug b/layout/includes/third-party/effect.pug index a6f3063..275297c 100644 --- a/layout/includes/third-party/effect.pug +++ b/layout/includes/third-party/effect.pug @@ -1,19 +1,19 @@ if theme.fireworks && theme.fireworks.enable canvas.fireworks(mobile=`${theme.fireworks.mobile}`) - script(src=url_for(theme.CDN.fireworks)) + script(src=url_for(theme.asset.fireworks)) if (theme.canvas_ribbon && theme.canvas_ribbon.enable) - script(defer id="ribbon" src=url_for(theme.CDN.canvas_ribbon) size=theme.canvas_ribbon.size + script(defer id="ribbon" src=url_for(theme.asset.canvas_ribbon) size=theme.canvas_ribbon.size alpha=theme.canvas_ribbon.alpha zIndex=theme.canvas_ribbon.zIndex mobile=`${theme.canvas_ribbon.mobile}` data-click=`${theme.canvas_ribbon.click_to_change}`) if (theme.canvas_fluttering_ribbon && theme.canvas_fluttering_ribbon.enable) - script(defer id="fluttering_ribbon" mobile=`${theme.canvas_fluttering_ribbon.mobile}` src=url_for(theme.CDN.canvas_fluttering_ribbon)) + script(defer id="fluttering_ribbon" mobile=`${theme.canvas_fluttering_ribbon.mobile}` src=url_for(theme.asset.canvas_fluttering_ribbon)) if (theme.canvas_nest && theme.canvas_nest.enable) - script#canvas_nest(defer color=theme.canvas_nest.color opacity=theme.canvas_nest.opacity zIndex=theme.canvas_nest.zIndex count=theme.canvas_nest.count mobile=`${theme.canvas_nest.mobile}` src=url_for(theme.CDN.canvas_nest)) + script#canvas_nest(defer color=theme.canvas_nest.color opacity=theme.canvas_nest.opacity zIndex=theme.canvas_nest.zIndex count=theme.canvas_nest.count mobile=`${theme.canvas_nest.mobile}` src=url_for(theme.asset.canvas_nest)) if theme.activate_power_mode.enable - script(src=url_for(theme.CDN.activate_power_mode)) + script(src=url_for(theme.asset.activate_power_mode)) script. POWERMODE.colorful = !{theme.activate_power_mode.colorful}; POWERMODE.shake = !{theme.activate_power_mode.shake}; @@ -22,11 +22,11 @@ if theme.activate_power_mode.enable //- 鼠標特效 if theme.click_heart && theme.click_heart.enable - script#click-heart(src=url_for(theme.CDN.click_heart) async mobile=`${theme.click_heart.mobile}`) + script#click-heart(src=url_for(theme.asset.click_heart) async mobile=`${theme.click_heart.mobile}`) if theme.ClickShowText && theme.ClickShowText.enable script#click-show-text( - src= url_for(theme.CDN.ClickShowText) + src= url_for(theme.asset.ClickShowText) data-mobile= `${theme.ClickShowText.mobile}` data-text= theme.ClickShowText.text.join(",") data-fontsize= theme.ClickShowText.fontSize diff --git a/layout/includes/third-party/math/katex.pug b/layout/includes/third-party/math/katex.pug index 028c626..9aa8301 100644 --- a/layout/includes/third-party/math/katex.pug +++ b/layout/includes/third-party/math/katex.pug @@ -1,6 +1,6 @@ -link(rel="stylesheet" type="text/css" href=theme.CDN.katex) -script(src=url_for(theme.CDN.katex_copytex)) -link(rel="stylesheet" type="text/css" href=theme.CDN.katex_copytex_css) +link(rel="stylesheet" type="text/css" href=theme.asset.katex) +script(src=url_for(theme.asset.katex_copytex)) +link(rel="stylesheet" type="text/css" href=theme.asset.katex_copytex_css) script. (() => { document.querySelectorAll('#article-container span.katex-display').forEach(item => { diff --git a/layout/includes/third-party/math/mathjax.pug b/layout/includes/third-party/math/mathjax.pug index b784218..f8b12bd 100644 --- a/layout/includes/third-party/math/mathjax.pug +++ b/layout/includes/third-party/math/mathjax.pug @@ -37,7 +37,7 @@ script. } const script = document.createElement('script') - script.src = '!{theme.CDN.mathjax}' + script.src = '!{theme.asset.mathjax}' script.id = 'MathJax-script' script.async = true document.head.appendChild(script) diff --git a/layout/includes/third-party/math/mermaid.pug b/layout/includes/third-party/math/mermaid.pug index 31dda5e..6bd8185 100644 --- a/layout/includes/third-party/math/mermaid.pug +++ b/layout/includes/third-party/math/mermaid.pug @@ -18,7 +18,7 @@ script. } const loadMermaid = () => { - window.loadMermaid ? runMermaid() : getScript('!{theme.CDN.mermaid}').then(runMermaid) + window.loadMermaid ? runMermaid() : getScript('!{theme.asset.mermaid}').then(runMermaid) } window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid) diff --git a/layout/includes/third-party/newest-comments/twikoo-comment.pug b/layout/includes/third-party/newest-comments/twikoo-comment.pug index 71b2803..9896b14 100644 --- a/layout/includes/third-party/newest-comments/twikoo-comment.pug +++ b/layout/includes/third-party/newest-comments/twikoo-comment.pug @@ -43,7 +43,7 @@ script. if (typeof twikoo === 'object') { runTwikoo() } else { - getScript('!{theme.CDN.twikoo}').then(runTwikoo) + getScript('!{theme.asset.twikoo}').then(runTwikoo) } } diff --git a/layout/includes/third-party/newest-comments/valine.pug b/layout/includes/third-party/newest-comments/valine.pug index dd39b13..ef0bb10 100644 --- a/layout/includes/third-party/newest-comments/valine.pug +++ b/layout/includes/third-party/newest-comments/valine.pug @@ -1,6 +1,6 @@ - let default_avatar = theme.valine.avatar -script(src=url_for(theme.CDN.blueimp_md5)) +script(src=url_for(theme.asset.blueimp_md5)) script. window.addEventListener('load', () => { const changeContent = (content) => { diff --git a/layout/includes/third-party/newest-comments/waline.pug b/layout/includes/third-party/newest-comments/waline.pug index ce0039e..15ca44c 100644 --- a/layout/includes/third-party/newest-comments/waline.pug +++ b/layout/includes/third-party/newest-comments/waline.pug @@ -1,5 +1,3 @@ -- let { avatar,avatarCDN } = theme.waline - script. window.addEventListener('load', () => { const changeContent = (content) => { @@ -45,11 +43,11 @@ script. const getComment = () => { const loadWaline = () => { - Waline.Widget.RecentComments({ + Waline.RecentComments({ serverURL: '!{theme.waline.serverURL}', count: !{theme.newest_comments.limit} - }).then(res => { - const walineArray = res.comments.map(e => { + }).then(({comments}) => { + const walineArray = comments.map(e => { return { 'content': changeContent(e.comment), 'avatar': e.avatar, @@ -67,7 +65,7 @@ script. } if (typeof Waline === 'function') loadWaline() - else getScript('!{url_for(theme.CDN.waline)}').then(loadWaline) + else getScript('!{url_for(theme.asset.waline_js)}').then(loadWaline) } const newestCommentInit = () => { diff --git a/layout/includes/third-party/pangu.pug b/layout/includes/third-party/pangu.pug index 7ac1395..2027ca7 100644 --- a/layout/includes/third-party/pangu.pug +++ b/layout/includes/third-party/pangu.pug @@ -2,7 +2,7 @@ script. function panguFn () { if (typeof pangu === 'object') pangu.autoSpacingPage() else { - getScript('!{url_for(theme.CDN.pangu)}') + getScript('!{url_for(theme.asset.pangu)}') .then(() => { pangu.autoSpacingPage() }) diff --git a/layout/includes/third-party/pjax.pug b/layout/includes/third-party/pjax.pug index abdb88d..de318d5 100644 --- a/layout/includes/third-party/pjax.pug +++ b/layout/includes/third-party/pjax.pug @@ -12,7 +12,7 @@ if choose if choose.includes('Utterances') || choose.includes('Giscus') - pjaxSelectors.unshift('link[rel="canonical"]') -script(src=url_for(theme.CDN.pjax)) +script(src=url_for(theme.asset.pjax)) script. let pjaxSelectors = !{JSON.stringify(pjaxSelectors)} diff --git a/layout/includes/third-party/prismjs.pug b/layout/includes/third-party/prismjs.pug index b277e25..6af44dd 100644 --- a/layout/includes/third-party/prismjs.pug +++ b/layout/includes/third-party/prismjs.pug @@ -1,5 +1,5 @@ if config.prismjs && config.prismjs.enable && !config.prismjs.preprocess - script(src=url_for(theme.CDN.prismjs_js)) - script(src=url_for(theme.CDN.prismjs_autoloader)) + script(src=url_for(theme.asset.prismjs_js)) + script(src=url_for(theme.asset.prismjs_autoloader)) if config.prismjs.line_number - script(src=url_for(theme.CDN.prismjs_lineNumber_js)) + script(src=url_for(theme.asset.prismjs_lineNumber_js)) diff --git a/layout/includes/third-party/search/algolia.pug b/layout/includes/third-party/search/algolia.pug index e2d427e..8a439e0 100644 --- a/layout/includes/third-party/search/algolia.pug +++ b/layout/includes/third-party/search/algolia.pug @@ -1,7 +1,7 @@ #algolia-search .search-dialog nav.search-nav - span.search-dialog-title= 'Algolia' + span.search-dialog-title= _p('search.title') button.search-close-button i.fas.fa-times @@ -11,6 +11,8 @@ #algolia-search-results #algolia-hits #algolia-pagination - #algolia-stats + #algolia-info + .algolia-stats + .algolia-poweredBy #search-mask diff --git a/layout/includes/third-party/search/local-search.pug b/layout/includes/third-party/search/local-search.pug index 4aa6ff3..3d1508f 100644 --- a/layout/includes/third-party/search/local-search.pug +++ b/layout/includes/third-party/search/local-search.pug @@ -1,7 +1,7 @@ #local-search .search-dialog nav.search-nav - span.search-dialog-title=_p("search.local_search.label") + span.search-dialog-title= _p('search.title') span#loading-status button.search-close-button i.fas.fa-times diff --git a/layout/includes/third-party/share/addtoany.pug b/layout/includes/third-party/share/addtoany.pug index a0a7aa2..d42f3be 100644 --- a/layout/includes/third-party/share/addtoany.pug +++ b/layout/includes/third-party/share/addtoany.pug @@ -5,6 +5,6 @@ a(class="a2a_button_" + name) a.a2a_dd(href="https://www.addtoany.com/share") -script(async src=url_for(theme.CDN.addtoany)) +script(async src='https://static.addtoany.com/menu/page.js') diff --git a/layout/includes/third-party/share/share-js.pug b/layout/includes/third-party/share/share-js.pug index 7cfaad2..0a566fa 100644 --- a/layout/includes/third-party/share/share-js.pug +++ b/layout/includes/third-party/share/share-js.pug @@ -1,3 +1,3 @@ .social-share(data-image=url_for(page.cover|| theme.avatar.img) data-sites= theme.sharejs.sites) -link(rel='stylesheet' href=url_for(theme.CDN.sharejs_css) media="print" onload="this.media='all'") -script(src=url_for(theme.CDN.sharejs) defer) \ No newline at end of file +link(rel='stylesheet' href=url_for(theme.asset.sharejs_css) media="print" onload="this.media='all'") +script(src=url_for(theme.asset.sharejs) defer) \ No newline at end of file diff --git a/layout/includes/third-party/subtitle.pug b/layout/includes/third-party/subtitle.pug index 21d705a..63915ec 100644 --- a/layout/includes/third-party/subtitle.pug +++ b/layout/includes/third-party/subtitle.pug @@ -29,7 +29,7 @@ case source if (typeof Typed === 'function') { subtitleType() } else { - getScript('!{url_for(theme.CDN.typed)}').then(subtitleType) + getScript('!{url_for(theme.asset.typed)}').then(subtitleType) } } else { subtitleType() @@ -61,7 +61,7 @@ case source if (typeof Typed === 'function') { subtitleType() } else { - getScript('!{url_for(theme.CDN.typed)}').then(subtitleType) + getScript('!{url_for(theme.asset.typed)}').then(subtitleType) } } else { subtitleType() @@ -94,7 +94,7 @@ case source if (typeof Typed === 'function') { subtitleType() } else { - getScript('!{url_for(theme.CDN.typed)}').then(subtitleType) + getScript('!{url_for(theme.asset.typed)}').then(subtitleType) } } else { subtitleType() @@ -121,7 +121,7 @@ case source if (typeof Typed === 'function') { subtitleType() } else { - getScript('!{url_for(theme.CDN.typed)}').then(subtitleType) + getScript('!{url_for(theme.asset.typed)}').then(subtitleType) } } else { subtitleType() diff --git a/layout/includes/widget/card_author.pug b/layout/includes/widget/card_author.pug index 0fa860a..de71edb 100644 --- a/layout/includes/widget/card_author.pug +++ b/layout/includes/widget/card_author.pug @@ -6,21 +6,16 @@ if theme.aside.card_author.enable .author-info__name= config.author .author-info__description!= theme.aside.card_author.description || config.description - .card-info-data.is-center - .card-info-data-item - a(href=url_for(config.archive_dir) + '/') - .headline= _p('aside.articles') - .length-num= site.posts.length - - .card-info-data-item - a(href=url_for(config.tag_dir) + '/') - .headline= _p('aside.tags') - .length-num= site.tags.length - - .card-info-data-item - a(href=url_for(config.category_dir) + '/') - .headline= _p('aside.categories') - .length-num= site.categories.length + .card-info-data.site-data.is-center + a(href=url_for(config.archive_dir) + '/') + .headline= _p('aside.articles') + .length-num= site.posts.length + a(href=url_for(config.tag_dir) + '/') + .headline= _p('aside.tags') + .length-num= site.tags.length + a(href=url_for(config.category_dir) + '/') + .headline= _p('aside.categories') + .length-num= site.categories.length if theme.aside.card_author.button.enable a#card-info-btn(href=theme.aside.card_author.button.link) diff --git a/package.json b/package.json index 0caf766..db7c603 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-butterfly", - "version": "4.1.0", + "version": "4.2.0", "description": "A Simple and Card UI Design theme for Hexo", "main": "package.json", "scripts": { diff --git a/scripts/events/config.js b/scripts/events/config.js index 33e663c..915ebb8 100644 --- a/scripts/events/config.js +++ b/scripts/events/config.js @@ -6,115 +6,120 @@ 'use strict' +const { version } = require('../../package.json') +const path = require('path') + hexo.extend.filter.register('before_generate', () => { const themeConfig = hexo.theme.config + const { CDN, comments } = themeConfig /** * Merge CDN */ - const defaultCDN = { + const internalSrcCDN = { + main_css: '/css/index.css', + main: `https://cdn.jsdelivr.net/npm/hexo-theme-butterfly@${version}/source/js/main.min.js`, + utils: `https://cdn.jsdelivr.net/npm/hexo-theme-butterfly@${version}/source/js/utils.min.js`, + translate: `https://cdn.jsdelivr.net/npm/hexo-theme-butterfly@${version}/source/js/tw_cn.min.js`, + local_search: `https://cdn.jsdelivr.net/npm/hexo-theme-butterfly@${version}/source/js/search/local-search.min.js`, + algolia_js: `https://cdn.jsdelivr.net/npm/hexo-theme-butterfly@${version}/source/js/search/algolia.min.js`, + } + + const internalSrcLocal = { main_css: '/css/index.css', main: '/js/main.js', utils: '/js/utils.js', + translate: '/js/tw_cn.js', + local_search: '/js/search/local-search.js', + algolia_js: '/js/search/algolia.js', + } - // pjax + const thirdPartySrcCDN = { + algolia_search_v4: 'https://cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch-lite.umd.js', + instantsearch_v4: 'https://cdn.jsdelivr.net/npm/instantsearch.js@4/dist/instantsearch.production.min.js', pjax: 'https://cdn.jsdelivr.net/npm/pjax/pjax.min.js', - - // comments gitalk: 'https://cdn.jsdelivr.net/npm/gitalk@latest/dist/gitalk.min.js', gitalk_css: 'https://cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.css', blueimp_md5: 'https://cdn.jsdelivr.net/npm/blueimp-md5/js/md5.min.js', valine: 'https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js', disqusjs: 'https://cdn.jsdelivr.net/npm/disqusjs@1/dist/disqus.js', disqusjs_css: 'https://cdn.jsdelivr.net/npm/disqusjs@1/dist/disqusjs.css', - utterances: 'https://utteranc.es/client.js', - twikoo: 'https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js', - waline: 'https://cdn.jsdelivr.net/npm/@waline/client/dist/Waline.min.js', - giscus: 'https://giscus.app/client.js', - - // share - addtoany: 'https://static.addtoany.com/menu/page.js', - sharejs: 'https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js', + twikoo: 'https://cdn.jsdelivr.net/npm/twikoo@1/dist/twikoo.all.min.js', + waline_js: 'https://cdn.jsdelivr.net/npm/@waline/client/dist/waline.js', + waline_css: 'https://cdn.jsdelivr.net/npm/@waline/client/dist/waline.css', + sharejs: 'https://cdn.jsdelivr.net/gh/overtrue/share.js@master/dist/js/social-share.min.js', sharejs_css: 'https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css', - - // search - local_search: '/js/search/local-search.js', - algolia_js: '/js/search/algolia.js', - algolia_search_v4: 'https://cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch-lite.umd.js', - instantsearch_v4: 'https://cdn.jsdelivr.net/npm/instantsearch.js@4/dist/instantsearch.production.min.js', - - // math mathjax: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js', katex: 'https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css', katex_copytex: 'https://cdn.jsdelivr.net/npm/katex@latest/dist/contrib/copy-tex.min.js', katex_copytex_css: 'https://cdn.jsdelivr.net/npm/katex@latest/dist/contrib/copy-tex.css', mermaid: 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js', - - // count - busuanzi: '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js', - - // background effect canvas_ribbon: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-ribbon.min.js', canvas_fluttering_ribbon: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-fluttering-ribbon.min.js', canvas_nest: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js', - - lazyload: 'https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js', - instantpage: 'https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js', - typed: 'https://cdn.jsdelivr.net/npm/typed.js/lib/typed.min.js', - pangu: 'https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js', - - // photo - fancybox_css_v4: 'https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css', - fancybox_v4: 'https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js', - medium_zoom: 'https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js', - - // snackbar - snackbar_css: 'https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css', - snackbar: 'https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js', - - // effect activate_power_mode: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js', fireworks: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/fireworks.min.js', click_heart: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js', ClickShowText: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-show-text.min.js', - - // fontawesome + lazyload: 'https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js', + instantpage: 'https://cdn.jsdelivr.net/npm/instant.page@5/instantpage.min.js', + typed: 'https://cdn.jsdelivr.net/npm/typed.js/lib/typed.min.js', + pangu: 'https://cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js', + fancybox_css_v4: 'https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css', + fancybox_v4: 'https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js', + medium_zoom: 'https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js', + snackbar_css: 'https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css', + snackbar: 'https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js', fontawesomeV6: 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/css/all.min.css', - - // Conversion between Traditional and Simplified Chinese - translate: '/js/tw_cn.js', - - // flickr-justified-gallery flickr_justified_gallery_js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.js', flickr_justified_gallery_css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.css', - - // aplayer - aplayer_css: 'https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css', - aplayer_js: 'https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js', + aplayer_css: 'https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.css', + aplayer_js: 'https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.js', meting_js: 'https://cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js', - - // Prism.js - prismjs_js: 'https://cdn.jsdelivr.net/npm/prismjs/prism.min.js', - prismjs_lineNumber_js: 'https://cdn.jsdelivr.net/npm/prismjs/plugins/line-numbers/prism-line-numbers.min.js', - prismjs_autoloader: 'https://cdn.jsdelivr.net/npm/prismjs/plugins/autoloader/prism-autoloader.min.js' + prismjs_js: 'https://cdn.jsdelivr.net/npm/prismjs@1/prism.min.js', + prismjs_lineNumber_js: 'https://cdn.jsdelivr.net/npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.js', + prismjs_autoloader: 'https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js', } // delete null value const deleteNullValue = obj => { + if (!obj) return for (const i in obj) { obj[i] === null && delete obj[i] } return obj } - themeConfig.CDN = Object.assign(defaultCDN, deleteNullValue(themeConfig.CDN)) + const defaultVal = (obj, choose) => { + if (obj === 'internal') { + if (choose === 'local') return internalSrcLocal + else return internalSrcCDN + } + + if (obj === 'external') { + if (choose === 'local') { + let result = {} + try { + const data = path.join(hexo.plugin_dir,'hexo-butterfly-extjs/plugins.yml') + result = hexo.render.renderSync({ path: data, engine: 'yaml'}) + Object.keys(result).map(key => { + result[key] = 'pluginsSrc/' + result[key] + }) + } catch (e) {} + return result + } else return thirdPartySrcCDN + } + } + + themeConfig.asset = Object.assign(defaultVal('internal', CDN.internal_provider), + defaultVal('external', CDN.third_party_provider), deleteNullValue(CDN.option)) /** * Capitalize the first letter of comment name */ - let { use } = themeConfig.comments + let { use } = comments if (!use) return diff --git a/scripts/helpers/inject_head_js.js b/scripts/helpers/inject_head_js.js index 8da1179..9c845d4 100644 --- a/scripts/helpers/inject_head_js.js +++ b/scripts/helpers/inject_head_js.js @@ -8,6 +8,10 @@ hexo.extend.helper.register('inject_head_js', function () { const { darkmode, aside } = this.theme + const { theme_color } = hexo.theme.config + const themeColorLight = theme_color && theme_color.enable && theme_color.meta_theme_color_light || '#ffffff' + const themeColorDark = theme_color && theme_color.enable && theme_color.meta_theme_color_dark || '#0d0d0d' + const localStore = ` win.saveToLocal = { set: function setWithExpiry(key, value, ttl) { @@ -62,13 +66,13 @@ hexo.extend.helper.register('inject_head_js', function () { win.activateDarkMode = function () { document.documentElement.setAttribute('data-theme', 'dark') if (document.querySelector('meta[name="theme-color"]') !== null) { - document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d') + document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorDark}') } } win.activateLightMode = function () { document.documentElement.setAttribute('data-theme', 'light') if (document.querySelector('meta[name="theme-color"]') !== null) { - document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff') + document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorLight}') } } const t = saveToLocal.get('theme') diff --git a/scripts/helpers/related_post.js b/scripts/helpers/related_post.js index 2f8371a..6809ac7 100644 --- a/scripts/helpers/related_post.js +++ b/scripts/helpers/related_post.js @@ -54,14 +54,15 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { relatedPosts[i].cover === false ? relatedPosts[i].randomcover : relatedPosts[i].cover - result += `
` + const title = this.escape_html(relatedPosts[i].title) + result += `
` result += `cover` if (dateType === 'created') { result += `' } diff --git a/source/css/_global/function.styl b/source/css/_global/function.styl index 7bc8d56..cf79eab 100644 --- a/source/css/_global/function.styl +++ b/source/css/_global/function.styl @@ -131,7 +131,7 @@ if hexo-config('enter_transitions') &.open for i in 1 2 3 4 > :nth-child({i}) - animation: sidebarItem (i / 5) s + animation: sidebarItem (i / 5)s .scroll-down-effects animation: scroll-down-effect 1.5s infinite diff --git a/source/css/_layout/aside.styl b/source/css/_layout/aside.styl index abb48b4..bc1675a 100644 --- a/source/css/_layout/aside.styl +++ b/source/css/_layout/aside.styl @@ -38,24 +38,7 @@ margin-top: -.42em .card-info-data - display: table margin: 14px 0 4px - width: 100% - table-layout: fixed - - & > .card-info-data-item - display: table-cell - - a - .headline - @extend .limit-one-line - color: var(--font-color) - font-size: 1em - - .length-num - margin-top: -.42em - color: var(--text-highlight-color) - font-size: 1.4em .card-info-social-icons margin: 6px 0 -6px @@ -340,6 +323,30 @@ &:hover transform: rotate(360deg) +.site-data + display: table + width: 100% + table-layout: fixed + + & > a + display: table-cell + + div + transition: all .3s + + &:hover + div + color: $theme-color !important + + .headline + @extend .limit-one-line + color: var(--font-color) + + .length-num + margin-top: -.32em + color: var(--text-highlight-color) + font-size: 1.4em + @keyframes more-btn-move 0%, 100% diff --git a/source/css/_layout/post.styl b/source/css/_layout/post.styl index e301801..aebae8d 100644 --- a/source/css/_layout/post.styl +++ b/source/css/_layout/post.styl @@ -152,6 +152,11 @@ beautify() #post .tag_share + &:after + display: block + clear: both + content: '' + .post-meta &__tag-list display: inline-block @@ -174,7 +179,7 @@ beautify() .post_share display: inline-block float: right - margin: 8px 0 20px + margin: 8px 0 0 width: fit-content .social-share diff --git a/source/css/_layout/sidebar.styl b/source/css/_layout/sidebar.styl index d557980..2e38ee8 100644 --- a/source/css/_layout/sidebar.styl +++ b/source/css/_layout/sidebar.styl @@ -25,24 +25,8 @@ & > .avatar-img margin: 20px auto - .site-data - display: table + .sidebar-site-data padding: 0 10px - width: 100% - table-layout: fixed - - .data-item - display: table-cell - - & > a > div - @extend .limit-one-line - - .length-num - color: var(--text-highlight-color) - font-size: 1.28em - - .headline - color: var(--font-color) hr margin: 20px auto diff --git a/source/css/_layout/third-party.styl b/source/css/_layout/third-party.styl index 8f52548..cf9483c 100644 --- a/source/css/_layout/third-party.styl +++ b/source/css/_layout/third-party.styl @@ -89,6 +89,7 @@ mjx-container[display], .has-jax overflow-x: auto overflow-y: hidden + line-height: normal !important .aplayer color: $font-black diff --git a/source/css/_search/algolia.styl b/source/css/_search/algolia.styl index c90c0a0..e9f06ce 100644 --- a/source/css/_search/algolia.styl +++ b/source/css/_search/algolia.styl @@ -11,7 +11,8 @@ color: var(--search-input-color) .ais-Hits-list - padding-left: 24px + margin: 0 + padding: 0 @extend .list-beauty a @@ -25,12 +26,17 @@ color: $search-keyword-highlight font-weight: bold + .algolia-hit-item-content + margin: 0 0 8px + word-break: break-all + .ais-Pagination - margin: 16px 0 0 + margin: 20px 0 0 padding: 0 text-align: center .ais-Pagination-list + margin: 0 padding: 0 list-style: none @@ -52,7 +58,34 @@ color: #eee cursor: default + .ais-Pagination-item--disabled + visibility: hidden + .algolia-logo padding-top: 2px width: 80px - height: 30px \ No newline at end of file + height: 30px + + #algolia-hits + > div + overflow-y: scroll + + +minWidth768() + max-height: calc(80vh - 240px) + + +maxWidth768() + height: calc(100vh - 260px) + + #algolia-info + div + display: inline + + .algolia-poweredBy + float: right + +.apple + #algolia-search + #algolia-hits + > div + +maxWidth768() + height: calc(90vh - 260px) diff --git a/source/css/_search/index.styl b/source/css/_search/index.styl index 2e4e874..bc5c5b1 100644 --- a/source/css/_search/index.styl +++ b/source/css/_search/index.styl @@ -1,6 +1,6 @@ .search-dialog position: fixed - top: 100px + top: 10% left: 50% z-index: 1001 display: none diff --git a/source/css/_search/local-search.styl b/source/css/_search/local-search.styl index f67d87a..bf99945 100644 --- a/source/css/_search/local-search.styl +++ b/source/css/_search/local-search.styl @@ -60,7 +60,7 @@ .search-result-list overflow-y: auto - max-height: 210px + max-height: calc(80vh - 130px) +maxWidth768() padding-bottom: 40px diff --git a/source/js/search/algolia.js b/source/js/search/algolia.js index 13373e9..530aa4d 100644 --- a/source/js/search/algolia.js +++ b/source/js/search/algolia.js @@ -26,16 +26,39 @@ window.addEventListener('load', () => { const searchClickFn = () => { document.querySelector('#search-button > .search').addEventListener('click', openSearch) + } + + const searchClickFnOnce = () => { document.getElementById('search-mask').addEventListener('click', closeSearch) document.querySelector('#algolia-search .search-close-button').addEventListener('click', closeSearch) } - searchClickFn() + const cutContent = content => { + if (content === '') return '' - window.addEventListener('pjax:complete', function () { - getComputedStyle(document.querySelector('#algolia-search .search-dialog')).display === 'block' && closeSearch() - searchClickFn() - }) + const firstOccur = content.indexOf('') + + let start = firstOccur - 30 + let end = firstOccur + 120 + let pre = '' + let post = '' + + if (start <= 0) { + start = 0 + end = 140 + } else { + pre = '...' + } + + if (end > content.length) { + end = content.length + } else { + post = '...' + } + + let matchContent = pre + content.substring(start, end) + post + return matchContent + } const algolia = GLOBAL_CONFIG.algolia const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName @@ -43,81 +66,89 @@ window.addEventListener('load', () => { return console.error('Algolia setting is invalid!') } - const searchClient = window.algoliasearch(algolia.appId, algolia.apiKey) const search = instantsearch({ indexName: algolia.indexName, - searchClient + searchClient: algoliasearch(algolia.appId, algolia.apiKey), + searchFunction(helper) { + helper.state.query && helper.search() + }, }) - search.addWidgets([ - instantsearch.widgets.configure({ - hitsPerPage: 5 - }) - ]) + const configure = instantsearch.widgets.configure({ + hitsPerPage: 5 + }) - search.addWidgets([ - instantsearch.widgets.searchBox({ - container: '#algolia-search-input', - showReset: false, - showSubmit: false, - placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder, - showLoadingIndicator: true - }) - ]) + const searchBox = instantsearch.widgets.searchBox({ + container: '#algolia-search-input', + showReset: false, + showSubmit: false, + placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder, + showLoadingIndicator: true + }) - search.addWidgets([ - instantsearch.widgets.hits({ - container: '#algolia-hits', - templates: { - item: function (data) { - const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path) - return ` - - ${data._highlightResult.title.value || 'no-title'} - ` - }, - empty: function (data) { - return ( - '
' + - GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) + - '
' - ) - } + const hits = instantsearch.widgets.hits({ + container: '#algolia-hits', + templates: { + item(data) { + const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path) + return ` + + ${data._highlightResult.title.value || 'no-title'} + +

${cutContent(data._highlightResult.contentStripTruncate.value)}

` + }, + empty: function (data) { + return ( + '
' + + GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) + + '
' + ) } - }) - ]) + } + }) - search.addWidgets([ - instantsearch.widgets.stats({ - container: '#algolia-stats', - templates: { - text: function (data) { - const icon = '' - const stats = GLOBAL_CONFIG.algolia.languages.hits_stats - .replace(/\$\{hits}/, data.nbHits) - .replace(/\$\{time}/, data.processingTimeMS) - return ( - `
${stats}` - ) - } + const stats = instantsearch.widgets.stats({ + container: '#algolia-info > .algolia-stats', + templates: { + text: function (data) { + const stats = GLOBAL_CONFIG.algolia.languages.hits_stats + .replace(/\$\{hits}/, data.nbHits) + .replace(/\$\{time}/, data.processingTimeMS) + return ( + `
${stats}` + ) } - }) - ]) + } + }) + + const powerBy = instantsearch.widgets.poweredBy({ + container: '#algolia-info > .algolia-poweredBy', + }) + + const pagination = instantsearch.widgets.pagination({ + container: '#algolia-pagination', + totalPages: 5, + templates: { + first: '', + last: '', + previous: '', + next: '' + } + }) + + + search.addWidgets([configure,searchBox,hits,stats,powerBy,pagination]) // add the widgets to the instantsearch instance - search.addWidgets([ - instantsearch.widgets.pagination({ - container: '#algolia-pagination', - totalPages: 5, - templates: { - first: '', - last: '', - previous: '', - next: '' - } - }) - ]) search.start() + searchClickFn() + searchClickFnOnce() + + window.addEventListener('pjax:complete', () => { + getComputedStyle(document.querySelector('#algolia-search .search-dialog')).display === 'block' && closeSearch() + searchClickFn() + }) + window.pjax && search.on('render', () => { window.pjax.refresh(document.getElementById('algolia-hits')) }) diff --git a/source/js/search/local-search.js b/source/js/search/local-search.js index 2d207d5..6c1ca7d 100644 --- a/source/js/search/local-search.js +++ b/source/js/search/local-search.js @@ -1,14 +1,17 @@ window.addEventListener('load', () => { let loadFlag = false + let dataObj = [] + const $searchMask = document.getElementById('search-mask') + const openSearch = () => { const bodyStyle = document.body.style bodyStyle.width = '100%' bodyStyle.overflow = 'hidden' - btf.animateIn(document.getElementById('search-mask'), 'to_show 0.5s') + btf.animateIn($searchMask, 'to_show 0.5s') btf.animateIn(document.querySelector('#local-search .search-dialog'), 'titleScale 0.5s') setTimeout(() => { document.querySelector('#local-search-input input').focus() }, 100) if (!loadFlag) { - search(GLOBAL_CONFIG.localSearch.path) + search() loadFlag = true } // shortcut: ESC @@ -25,35 +28,35 @@ window.addEventListener('load', () => { bodyStyle.width = '' bodyStyle.overflow = '' btf.animateOut(document.querySelector('#local-search .search-dialog'), 'search_close .5s') - btf.animateOut(document.getElementById('search-mask'), 'to_hide 0.5s') + btf.animateOut($searchMask, 'to_hide 0.5s') } - // click function const searchClickFn = () => { document.querySelector('#search-button > .search').addEventListener('click', openSearch) - document.getElementById('search-mask').addEventListener('click', closeSearch) - document.querySelector('#local-search .search-close-button').addEventListener('click', closeSearch) } - searchClickFn() + const searchClickFnOnce = () => { + document.querySelector('#local-search .search-close-button').addEventListener('click', closeSearch) + $searchMask.addEventListener('click', closeSearch) + if (GLOBAL_CONFIG.localSearch.preload) dataObj = fetchData(GLOBAL_CONFIG.localSearch.path) + } - // pjax - window.addEventListener('pjax:complete', function () { - getComputedStyle(document.querySelector('#local-search .search-dialog')).display === 'block' && closeSearch() - searchClickFn() - }) + // check url is json or not + const isJson = url => { + const reg = /\.json$/ + return reg.test(url) + } - async function search (path) { - let datas = [] - const typeF = path.split('.')[1] - const response = await fetch(GLOBAL_CONFIG.root + path) - if (typeF === 'json') { - datas = await response.json() - } else if (typeF === 'xml') { + const fetchData = async (path) => { + let data = [] + const response = await fetch(path) + if (isJson(path)) { + data = await response.json() + } else { const res = await response.text() const t = await new window.DOMParser().parseFromString(res, 'text/xml') const a = await t - datas = [...a.querySelectorAll('entry')].map(function (item) { + data = [...a.querySelectorAll('entry')].map(item =>{ return { title: item.querySelector('title').textContent, content: item.querySelector('content') && item.querySelector('content').textContent, @@ -66,10 +69,18 @@ window.addEventListener('load', () => { $loadDataItem.nextElementSibling.style.display = 'block' $loadDataItem.remove() } + return data + } + + const search = () => { + if (!GLOBAL_CONFIG.localSearch.preload) { + dataObj = fetchData(GLOBAL_CONFIG.localSearch.path) + } const $input = document.querySelector('#local-search-input input') const $resultContent = document.getElementById('local-search-results') const $loadingStatus = document.getElementById('loading-status') + $input.addEventListener('input', function () { const keywords = this.value.trim().toLowerCase().split(/[\s]+/) if (keywords[0] !== '') $loadingStatus.innerHTML = '' @@ -79,82 +90,99 @@ window.addEventListener('load', () => { if (keywords.length <= 0) return let count = 0 // perform local searching - datas.forEach(function (data) { - let isMatch = true - let dataTitle = data.title ? data.title.trim().toLowerCase() : '' - const dataContent = data.content ? data.content.trim().replace(/<[^>]+>/g, '').toLowerCase() : '' - const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url - let indexTitle = -1 - let indexContent = -1 - let firstOccur = -1 - // only match artiles with not empty titles and contents - if (dataTitle !== '' || dataContent !== '') { - keywords.forEach(function (keyword, i) { - indexTitle = dataTitle.indexOf(keyword) - indexContent = dataContent.indexOf(keyword) - if (indexTitle < 0 && indexContent < 0) { - isMatch = false - } else { - if (indexContent < 0) { - indexContent = 0 + dataObj.then(data => { + data.forEach(data => { + let isMatch = true + let dataTitle = data.title ? data.title.trim().toLowerCase() : '' + const dataContent = data.content ? data.content.trim().replace(/<[^>]+>/g, '').toLowerCase() : '' + const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url + let indexTitle = -1 + let indexContent = -1 + let firstOccur = -1 + // only match articles with not empty titles and contents + if (dataTitle !== '' || dataContent !== '') { + keywords.forEach((keyword, i) => { + indexTitle = dataTitle.indexOf(keyword) + indexContent = dataContent.indexOf(keyword) + if (indexTitle < 0 && indexContent < 0) { + isMatch = false + } else { + if (indexContent < 0) { + indexContent = 0 + } + if (i === 0) { + firstOccur = indexContent + } } - if (i === 0) { - firstOccur = indexContent - } - } - }) - } else { - isMatch = false - } - - // show search results - if (isMatch) { - if (firstOccur >= 0) { - // cut out 130 characters - // let start = firstOccur - 30 < 0 ? 0 : firstOccur - 30 - // let end = firstOccur + 50 > dataContent.length ? dataContent.length : firstOccur + 50 - let start = firstOccur - 30 - let end = firstOccur + 100 - - if (start < 0) { - start = 0 - } - - if (start === 0) { - end = 100 - } - - if (end > dataContent.length) { - end = dataContent.length - } - - let matchContent = dataContent.substring(start, end) - - // highlight all keywords - keywords.forEach(function (keyword) { - const regS = new RegExp(keyword, 'gi') - matchContent = matchContent.replace(regS, '' + keyword + '') - dataTitle = dataTitle.replace(regS, '' + keyword + '') }) - - str += '
' + dataTitle + '' - count += 1 - - if (dataContent !== '') { - str += '

' + matchContent + '...

' - } + } else { + isMatch = false } - str += '
' + + // show search results + if (isMatch) { + if (firstOccur >= 0) { + // cut out 130 characters + // let start = firstOccur - 30 < 0 ? 0 : firstOccur - 30 + // let end = firstOccur + 50 > dataContent.length ? dataContent.length : firstOccur + 50 + let start = firstOccur - 30 + let end = firstOccur + 100 + let pre = '' + let post = '' + + if (start < 0) { + start = 0 + } + + if (start === 0) { + end = 100 + } else { + pre = '...' + } + + if (end > dataContent.length) { + end = dataContent.length + } else { + post = '...' + } + + let matchContent = dataContent.substring(start, end) + + // highlight all keywords + keywords.forEach(keyword => { + const regS = new RegExp(keyword, 'gi') + matchContent = matchContent.replace(regS, '' + keyword + '') + dataTitle = dataTitle.replace(regS, '' + keyword + '') + }) + + str += '
' + dataTitle + '' + count += 1 + + if (dataContent !== '') { + str += '

' + pre + matchContent + post + '

' + } + } + str += '
' + } + }) + if (count === 0) { + str += '
' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) + + '
' } + str += '
' + $resultContent.innerHTML = str + if (keywords[0] !== '') $loadingStatus.innerHTML = '' + window.pjax && window.pjax.refresh($resultContent) }) - if (count === 0) { - str += '
' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) + - '
' - } - str += '
' - $resultContent.innerHTML = str - if (keywords[0] !== '') $loadingStatus.innerHTML = '' - window.pjax && window.pjax.refresh($resultContent) }) } + + searchClickFn() + searchClickFnOnce() + + // pjax + window.addEventListener('pjax:complete', () => { + !btf.isHidden($searchMask) && closeSearch() + searchClickFn() + }) })