From 9eb7a32d235ce550b1ed5fb923d2307d3b582b68 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, 21 May 2022 17:47:26 +0800 Subject: [PATCH] :building_construction: First time sync the css & js files from hexo theme NexT --- .gitignore | 6 + LICENSE | 20 + README.md | 9 + archetypes/default.md | 21 + assets/css/_colors.scss | 76 ++ .../css/_common/components/back-to-top.scss | 45 + assets/css/_common/components/index.scss | 20 + .../_common/components/pages/breadcrumb.scss | 21 + .../_common/components/pages/categories.scss | 35 + .../css/_common/components/pages/index.scss | 5 + .../_common/components/pages/schedule.scss | 102 ++ .../_common/components/pages/tag-cloud.scss | 28 + assets/css/_common/components/post/index.scss | 53 + .../_common/components/post/post-body.scss | 79 ++ .../components/post/post-collapse.scss | 109 +++ .../components/post/post-followme.scss | 35 + .../_common/components/post/post-footer.scss | 41 + .../_common/components/post/post-gallery.scss | 33 + .../_common/components/post/post-header.scss | 120 +++ .../css/_common/components/post/post-nav.scss | 41 + .../_common/components/post/post-reward.scss | 56 ++ .../_common/components/post/post-widgets.scss | 20 + .../_common/components/reading-progress.scss | 27 + .../components/third-party/disqusjs.styl | 39 + .../components/third-party/gitalk.scss | 9 + .../components/third-party/gitter.styl | 7 + .../_common/components/third-party/index.scss | 18 + .../_common/components/third-party/math.scss | 9 + .../components/third-party/related-posts.scss | 23 + .../components/third-party/search.scss | 179 ++++ .../components/third-party/utterances.scss | 5 + assets/css/_common/outline/footer/index.scss | 100 ++ .../css/_common/outline/header/bookmark.scss | 24 + .../_common/outline/header/github-banner.scss | 59 ++ assets/css/_common/outline/header/index.scss | 38 + assets/css/_common/outline/header/menu.scss | 56 ++ .../css/_common/outline/header/site-meta.scss | 49 + .../css/_common/outline/header/site-nav.scss | 24 + assets/css/_common/outline/index.scss | 5 + assets/css/_common/outline/mobile.scss | 85 ++ assets/css/_common/outline/sidebar/index.scss | 38 + .../outline/sidebar/sidebar-author-links.scss | 11 + .../outline/sidebar/sidebar-author.scss | 29 + .../outline/sidebar/sidebar-blogroll.scss | 15 + .../outline/sidebar/sidebar-button.scss | 15 + .../outline/sidebar/sidebar-dimmer.scss | 24 + .../_common/outline/sidebar/sidebar-nav.scss | 57 ++ .../_common/outline/sidebar/sidebar-toc.scss | 61 ++ .../outline/sidebar/sidebar-toggle.scss | 21 + .../_common/outline/sidebar/site-state.scss | 28 + assets/css/_common/scaffolding/base.scss | 99 ++ assets/css/_common/scaffolding/buttons.scss | 26 + assets/css/_common/scaffolding/comments.scss | 39 + .../scaffolding/highlight/copy-code.scss | 55 ++ .../_common/scaffolding/highlight/index.scss | 140 +++ assets/css/_common/scaffolding/index.scss | 12 + assets/css/_common/scaffolding/normalize.scss | 289 ++++++ .../css/_common/scaffolding/pagination.scss | 55 ++ assets/css/_common/scaffolding/tables.scss | 39 + .../scaffolding/tags/blockquote-center.scss | 34 + .../scaffolding/tags/group-pictures.scss | 20 + .../css/_common/scaffolding/tags/index.scss | 8 + .../css/_common/scaffolding/tags/label.scss | 12 + .../_common/scaffolding/tags/link-grid.scss | 113 +++ .../css/_common/scaffolding/tags/mermaid.scss | 6 + assets/css/_common/scaffolding/tags/note.scss | 114 +++ assets/css/_common/scaffolding/tags/pdf.scss | 8 + assets/css/_common/scaffolding/tags/tabs.scss | 103 ++ assets/css/_common/scaffolding/toggles.scss | 26 + assets/css/_mixins.scss | 243 +++++ assets/css/_schemes/Gemini/index.scss | 130 +++ assets/css/_schemes/Mist/_header.scss | 56 ++ assets/css/_schemes/Mist/_layout.scss | 43 + assets/css/_schemes/Mist/_menu.scss | 45 + assets/css/_schemes/Mist/_posts-expand.scss | 72 ++ assets/css/_schemes/Mist/index.scss | 10 + assets/css/_schemes/Muse/_header.scss | 18 + assets/css/_schemes/Muse/_layout.scss | 28 + assets/css/_schemes/Muse/_menu.scss | 56 ++ assets/css/_schemes/Muse/_sidebar.scss | 94 ++ assets/css/_schemes/Muse/_sub-menu.scss | 7 + assets/css/_schemes/Muse/index.scss | 5 + assets/css/_schemes/Pisces/_header.scss | 35 + assets/css/_schemes/Pisces/_layout.scss | 54 ++ assets/css/_schemes/Pisces/_menu.scss | 46 + assets/css/_schemes/Pisces/_sidebar.scss | 92 ++ assets/css/_schemes/Pisces/_sub-menu.scss | 28 + assets/css/_schemes/Pisces/index.scss | 30 + assets/css/_variables/Gemini.scss | 18 + assets/css/_variables/Mist.scss | 25 + assets/css/_variables/Muse.scss | 9 + assets/css/_variables/Pisces.scss | 68 ++ assets/css/_variables/base.scss | 394 ++++++++ assets/css/main.scss | 42 + assets/css/noscript.scss | 30 + assets/js/bookmark.js | 56 ++ assets/js/comments-buttons.js | 25 + assets/js/comments.js | 21 + assets/js/config.js | 66 ++ assets/js/motion.js | 125 +++ assets/js/next-boot.js | 75 ++ assets/js/pjax.js | 34 + assets/js/schedule.js | 138 +++ assets/js/schemes/muse.js | 60 ++ .../third-party/analytics/baidu-analytics.js | 7 + .../third-party/analytics/google-analytics.js | 35 + assets/js/third-party/analytics/growingio.js | 10 + assets/js/third-party/chat/chatra.js | 19 + assets/js/third-party/chat/gitter.js | 5 + assets/js/third-party/chat/tidio.js | 10 + assets/js/third-party/comments/changyan.js | 39 + assets/js/third-party/comments/disqus.js | 41 + assets/js/third-party/comments/disqusjs.js | 18 + assets/js/third-party/comments/gitalk.js | 24 + assets/js/third-party/comments/isso.js | 15 + assets/js/third-party/comments/livere.js | 19 + assets/js/third-party/comments/utterances.js | 17 + assets/js/third-party/fancybox.js | 38 + assets/js/third-party/math/katex.js | 7 + assets/js/third-party/math/mathjax.js | 36 + assets/js/third-party/pace.js | 7 + assets/js/third-party/quicklink.js | 37 + assets/js/third-party/rating.js | 22 + .../js/third-party/search/algolia-search.js | 130 +++ assets/js/third-party/search/local-search.js | 99 ++ assets/js/third-party/statistics/firestore.js | 64 ++ .../third-party/statistics/lean-analytics.js | 102 ++ assets/js/third-party/tags/mermaid.js | 32 + assets/js/third-party/tags/pdf.js | 23 + assets/js/utils.js | 399 ++++++++ exampleSite/config.yaml | 907 ++++++++++++++++++ exampleSite/content/hello-world.md | 59 ++ i18n/en-us.toml | 49 + i18n/zh-cn.toml | 49 + layouts/404.html | 0 layouts/_default/baseof.html | 11 + layouts/_default/list.html | 0 layouts/_default/single.html | 0 layouts/index.html | 2 + layouts/partials/footer.html | 0 layouts/partials/head.html | 0 layouts/partials/header.html | 0 static/css/hover.css | 176 ++++ static/imgs/cc/big/by.svg | 1 + static/imgs/cc/big/by_nc.svg | 1 + static/imgs/cc/big/by_nc_nd.svg | 1 + static/imgs/cc/big/by_nc_sa.svg | 1 + static/imgs/cc/big/by_nd.svg | 1 + static/imgs/cc/big/by_sa.svg | 1 + static/imgs/cc/big/cc_zero.svg | 1 + static/imgs/cc/cc.svg | 1 + static/imgs/cc/small/by.svg | 1 + static/imgs/cc/small/by_nc.svg | 1 + static/imgs/cc/small/by_nc_nd.svg | 1 + static/imgs/cc/small/by_nc_sa.svg | 1 + static/imgs/cc/small/by_nd.svg | 1 + static/imgs/cc/small/by_sa.svg | 1 + static/imgs/cc/small/cc_zero.svg | 1 + static/imgs/gongan.png | Bin 0 -> 869 bytes static/imgs/hugo_next_avatar.png | Bin 0 -> 1120 bytes static/imgs/hugo_next_logo.png | Bin 0 -> 31634 bytes static/imgs/icons/apple_touch_icon_next.png | Bin 0 -> 1699 bytes static/imgs/icons/favicon.ico | Bin 0 -> 4286 bytes static/imgs/icons/favicon_16x16_next.png | Bin 0 -> 345 bytes static/imgs/icons/favicon_32_32_next.png | Bin 0 -> 429 bytes static/js/index.js | 1 + theme.toml | 13 + 167 files changed, 8043 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 archetypes/default.md create mode 100644 assets/css/_colors.scss create mode 100644 assets/css/_common/components/back-to-top.scss create mode 100644 assets/css/_common/components/index.scss create mode 100644 assets/css/_common/components/pages/breadcrumb.scss create mode 100644 assets/css/_common/components/pages/categories.scss create mode 100644 assets/css/_common/components/pages/index.scss create mode 100644 assets/css/_common/components/pages/schedule.scss create mode 100644 assets/css/_common/components/pages/tag-cloud.scss create mode 100644 assets/css/_common/components/post/index.scss create mode 100644 assets/css/_common/components/post/post-body.scss create mode 100644 assets/css/_common/components/post/post-collapse.scss create mode 100644 assets/css/_common/components/post/post-followme.scss create mode 100644 assets/css/_common/components/post/post-footer.scss create mode 100644 assets/css/_common/components/post/post-gallery.scss create mode 100644 assets/css/_common/components/post/post-header.scss create mode 100644 assets/css/_common/components/post/post-nav.scss create mode 100644 assets/css/_common/components/post/post-reward.scss create mode 100644 assets/css/_common/components/post/post-widgets.scss create mode 100644 assets/css/_common/components/reading-progress.scss create mode 100644 assets/css/_common/components/third-party/disqusjs.styl create mode 100644 assets/css/_common/components/third-party/gitalk.scss create mode 100644 assets/css/_common/components/third-party/gitter.styl create mode 100644 assets/css/_common/components/third-party/index.scss create mode 100644 assets/css/_common/components/third-party/math.scss create mode 100644 assets/css/_common/components/third-party/related-posts.scss create mode 100644 assets/css/_common/components/third-party/search.scss create mode 100644 assets/css/_common/components/third-party/utterances.scss create mode 100644 assets/css/_common/outline/footer/index.scss create mode 100644 assets/css/_common/outline/header/bookmark.scss create mode 100644 assets/css/_common/outline/header/github-banner.scss create mode 100644 assets/css/_common/outline/header/index.scss create mode 100644 assets/css/_common/outline/header/menu.scss create mode 100644 assets/css/_common/outline/header/site-meta.scss create mode 100644 assets/css/_common/outline/header/site-nav.scss create mode 100644 assets/css/_common/outline/index.scss create mode 100644 assets/css/_common/outline/mobile.scss create mode 100644 assets/css/_common/outline/sidebar/index.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-author-links.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-author.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-blogroll.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-button.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-dimmer.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-nav.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-toc.scss create mode 100644 assets/css/_common/outline/sidebar/sidebar-toggle.scss create mode 100644 assets/css/_common/outline/sidebar/site-state.scss create mode 100644 assets/css/_common/scaffolding/base.scss create mode 100644 assets/css/_common/scaffolding/buttons.scss create mode 100644 assets/css/_common/scaffolding/comments.scss create mode 100644 assets/css/_common/scaffolding/highlight/copy-code.scss create mode 100644 assets/css/_common/scaffolding/highlight/index.scss create mode 100644 assets/css/_common/scaffolding/index.scss create mode 100644 assets/css/_common/scaffolding/normalize.scss create mode 100644 assets/css/_common/scaffolding/pagination.scss create mode 100644 assets/css/_common/scaffolding/tables.scss create mode 100644 assets/css/_common/scaffolding/tags/blockquote-center.scss create mode 100644 assets/css/_common/scaffolding/tags/group-pictures.scss create mode 100644 assets/css/_common/scaffolding/tags/index.scss create mode 100644 assets/css/_common/scaffolding/tags/label.scss create mode 100644 assets/css/_common/scaffolding/tags/link-grid.scss create mode 100644 assets/css/_common/scaffolding/tags/mermaid.scss create mode 100644 assets/css/_common/scaffolding/tags/note.scss create mode 100644 assets/css/_common/scaffolding/tags/pdf.scss create mode 100644 assets/css/_common/scaffolding/tags/tabs.scss create mode 100644 assets/css/_common/scaffolding/toggles.scss create mode 100644 assets/css/_mixins.scss create mode 100644 assets/css/_schemes/Gemini/index.scss create mode 100644 assets/css/_schemes/Mist/_header.scss create mode 100644 assets/css/_schemes/Mist/_layout.scss create mode 100644 assets/css/_schemes/Mist/_menu.scss create mode 100644 assets/css/_schemes/Mist/_posts-expand.scss create mode 100644 assets/css/_schemes/Mist/index.scss create mode 100644 assets/css/_schemes/Muse/_header.scss create mode 100644 assets/css/_schemes/Muse/_layout.scss create mode 100644 assets/css/_schemes/Muse/_menu.scss create mode 100644 assets/css/_schemes/Muse/_sidebar.scss create mode 100644 assets/css/_schemes/Muse/_sub-menu.scss create mode 100644 assets/css/_schemes/Muse/index.scss create mode 100644 assets/css/_schemes/Pisces/_header.scss create mode 100644 assets/css/_schemes/Pisces/_layout.scss create mode 100644 assets/css/_schemes/Pisces/_menu.scss create mode 100644 assets/css/_schemes/Pisces/_sidebar.scss create mode 100644 assets/css/_schemes/Pisces/_sub-menu.scss create mode 100644 assets/css/_schemes/Pisces/index.scss create mode 100644 assets/css/_variables/Gemini.scss create mode 100644 assets/css/_variables/Mist.scss create mode 100644 assets/css/_variables/Muse.scss create mode 100644 assets/css/_variables/Pisces.scss create mode 100644 assets/css/_variables/base.scss create mode 100644 assets/css/main.scss create mode 100644 assets/css/noscript.scss create mode 100644 assets/js/bookmark.js create mode 100644 assets/js/comments-buttons.js create mode 100644 assets/js/comments.js create mode 100644 assets/js/config.js create mode 100644 assets/js/motion.js create mode 100644 assets/js/next-boot.js create mode 100644 assets/js/pjax.js create mode 100644 assets/js/schedule.js create mode 100644 assets/js/schemes/muse.js create mode 100644 assets/js/third-party/analytics/baidu-analytics.js create mode 100644 assets/js/third-party/analytics/google-analytics.js create mode 100644 assets/js/third-party/analytics/growingio.js create mode 100644 assets/js/third-party/chat/chatra.js create mode 100644 assets/js/third-party/chat/gitter.js create mode 100644 assets/js/third-party/chat/tidio.js create mode 100644 assets/js/third-party/comments/changyan.js create mode 100644 assets/js/third-party/comments/disqus.js create mode 100644 assets/js/third-party/comments/disqusjs.js create mode 100644 assets/js/third-party/comments/gitalk.js create mode 100644 assets/js/third-party/comments/isso.js create mode 100644 assets/js/third-party/comments/livere.js create mode 100644 assets/js/third-party/comments/utterances.js create mode 100644 assets/js/third-party/fancybox.js create mode 100644 assets/js/third-party/math/katex.js create mode 100644 assets/js/third-party/math/mathjax.js create mode 100644 assets/js/third-party/pace.js create mode 100644 assets/js/third-party/quicklink.js create mode 100644 assets/js/third-party/rating.js create mode 100644 assets/js/third-party/search/algolia-search.js create mode 100644 assets/js/third-party/search/local-search.js create mode 100644 assets/js/third-party/statistics/firestore.js create mode 100644 assets/js/third-party/statistics/lean-analytics.js create mode 100644 assets/js/third-party/tags/mermaid.js create mode 100644 assets/js/third-party/tags/pdf.js create mode 100644 assets/js/utils.js create mode 100644 exampleSite/config.yaml create mode 100644 exampleSite/content/hello-world.md create mode 100644 i18n/en-us.toml create mode 100644 i18n/zh-cn.toml create mode 100644 layouts/404.html create mode 100644 layouts/_default/baseof.html create mode 100644 layouts/_default/list.html create mode 100644 layouts/_default/single.html create mode 100644 layouts/index.html create mode 100644 layouts/partials/footer.html create mode 100644 layouts/partials/head.html create mode 100644 layouts/partials/header.html create mode 100644 static/css/hover.css create mode 100644 static/imgs/cc/big/by.svg create mode 100644 static/imgs/cc/big/by_nc.svg create mode 100644 static/imgs/cc/big/by_nc_nd.svg create mode 100644 static/imgs/cc/big/by_nc_sa.svg create mode 100644 static/imgs/cc/big/by_nd.svg create mode 100644 static/imgs/cc/big/by_sa.svg create mode 100644 static/imgs/cc/big/cc_zero.svg create mode 100644 static/imgs/cc/cc.svg create mode 100644 static/imgs/cc/small/by.svg create mode 100644 static/imgs/cc/small/by_nc.svg create mode 100644 static/imgs/cc/small/by_nc_nd.svg create mode 100644 static/imgs/cc/small/by_nc_sa.svg create mode 100644 static/imgs/cc/small/by_nd.svg create mode 100644 static/imgs/cc/small/by_sa.svg create mode 100644 static/imgs/cc/small/cc_zero.svg create mode 100644 static/imgs/gongan.png create mode 100644 static/imgs/hugo_next_avatar.png create mode 100644 static/imgs/hugo_next_logo.png create mode 100644 static/imgs/icons/apple_touch_icon_next.png create mode 100644 static/imgs/icons/favicon.ico create mode 100644 static/imgs/icons/favicon_16x16_next.png create mode 100644 static/imgs/icons/favicon_32_32_next.png create mode 100644 static/js/index.js create mode 100644 theme.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..470f243 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Ignore files in Hugo NexT theme + +.hugo_build.lock + +exampleSite/public +exampleSite/resources \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..807bb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2022 hugo-next + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6906e1 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Hugo theme of NexT + +![hugo-next-primary](https://lisenhui.gitee.io/imgs/hugo-next/logo/hugo-next-primary.png) + +Start a new journey for Hugo's theme of NexT. + +# Our Vision + +Make `NexT` theme is easily & powerful. \ No newline at end of file diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..518c212 --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,21 @@ +--- +title: '{{ replace .Name "-" " " | title }}' +description: 'Short description of the article.' +keywords: 'Key words' +isCJKLanguage: true + +author: 'Author of the article' +lastmod: '{{ .Date }}' +publishDate: '{{ .Date }}' +weight: 1 + +categories: + - +tags: + - + - + +toc: false +draft: true +url: '{{ lower .Name }}.html' +--- diff --git a/assets/css/_colors.scss b/assets/css/_colors.scss new file mode 100644 index 0000000..0f3ed70 --- /dev/null +++ b/assets/css/_colors.scss @@ -0,0 +1,76 @@ +:root { + // https://sass-lang.com/documentation/breaking-changes/css-vars + --body-bg-color: #{$body-bg-color}; + --content-bg-color: #{$content-bg-color}; + --card-bg-color: #{$card-bg-color}; + --text-color: #{$text-color}; + --blockquote-color: #{$blockquote-color}; + --link-color: #{$link-color}; + --link-hover-color: #{$link-hover-color}; + --brand-color: #{$brand-color}; + --brand-hover-color: #{$brand-hover-color}; + --table-row-odd-bg-color: #{$table-row-odd-bg-color}; + --table-row-hover-bg-color: #{$table-row-hover-bg-color}; + --menu-item-bg-color: #{$menu-item-bg-color}; + --theme-color: #{$theme-color}; + + --btn-default-bg: #{$btn-default-bg}; + --btn-default-color: #{$btn-default-color}; + --btn-default-border-color: #{$btn-default-border-color}; + --btn-default-hover-bg: #{$btn-default-hover-bg}; + --btn-default-hover-color: #{$btn-default-hover-color}; + --btn-default-hover-border-color: #{$btn-default-hover-border-color}; + + --highlight-background: #{$highlight-background}; + --highlight-foreground: #{$highlight-foreground}; + --highlight-gutter-background: #{$highlight-gutter-background}; + --highlight-gutter-foreground: #{$highlight-gutter-foreground}; + + color-scheme: light; +} + +@if hexo-config('darkmode') { + @media (prefers-color-scheme: dark) { + :root { + --body-bg-color: #{$body-bg-color-dark}; + --content-bg-color: #{$content-bg-color-dark}; + --card-bg-color: #{$card-bg-color-dark}; + --text-color: #{$text-color-dark}; + --blockquote-color: #{$blockquote-color-dark}; + --link-color: #{$link-color-dark}; + --link-hover-color: #{$link-hover-color-dark}; + --brand-color: #{$brand-color-dark}; + --brand-hover-color: #{$brand-hover-color-dark}; + --table-row-odd-bg-color: #{$table-row-odd-bg-color-dark}; + --table-row-hover-bg-color: #{$table-row-hover-bg-color-dark}; + --menu-item-bg-color: #{$menu-item-bg-color-dark}; + --theme-color: #{$theme-color-dark}; + + --btn-default-bg: #{$btn-default-bg-dark}; + --btn-default-color: #{$btn-default-color-dark}; + --btn-default-border-color: #{$btn-default-border-color-dark}; + --btn-default-hover-bg: #{$btn-default-hover-bg-dark}; + --btn-default-hover-color: #{$btn-default-hover-color-dark}; + --btn-default-hover-border-color: #{$btn-default-hover-border-color-dark}; + + --highlight-background: #{$highlight-background-dark}; + --highlight-foreground: #{$highlight-foreground-dark}; + --highlight-gutter-background: #{$highlight-gutter-background-dark}; + --highlight-gutter-foreground: #{$highlight-gutter-foreground-dark}; + + color-scheme: dark; + } + + img { + opacity: .75; + + &:hover { + opacity: .9; + } + } + + iframe { + color-scheme: light; + } + } +} diff --git a/assets/css/_common/components/back-to-top.scss b/assets/css/_common/components/back-to-top.scss new file mode 100644 index 0000000..97316c8 --- /dev/null +++ b/assets/css/_common/components/back-to-top.scss @@ -0,0 +1,45 @@ +@if hexo-config('back2top.enable') { + .back-to-top { + font-size: $b2t-font-size; + + @if not hexo-config('back2top.scrollpercent') { + span { + display: none; + } + } + + @if hexo-config('back2top.sidebar') { + margin: 20px - $sidebar-offset -10px -20px; + opacity: 0; + transition: opacity $transition-ease; + + &.back-to-top-on { + cursor: pointer; + opacity: $b2t-opacity; + + &:hover { + opacity: $b2t-opacity-hover; + } + } + } @else { + bottom: $b2t-position-bottom; + box-sizing: border-box; + color: $b2t-color; + padding: 0 6px; + transition: bottom $transition-ease; + @include sidebar-toggle(); + + @if not hexo-config('back2top.scrollpercent') { + width: 24px; + } + + &:hover { + color: $sidebar-highlight; + } + + &.back-to-top-on { + bottom: $b2t-position-bottom-on; + } + } + } +} diff --git a/assets/css/_common/components/index.scss b/assets/css/_common/components/index.scss new file mode 100644 index 0000000..77f5cd3 --- /dev/null +++ b/assets/css/_common/components/index.scss @@ -0,0 +1,20 @@ +.noscript-warning { + background-color: lighten($red, 20%); + color: white; + font-family: sans-serif; + font-size: 1rem; + font-weight: bold; + left: 0; + position: fixed; + text-align: center; + top: 0; + width: 100%; + z-index: $zindex-5; +} + +@import 'back-to-top'; +@import 'reading-progress'; + +@import 'post'; +@import 'pages'; +@import 'third-party'; diff --git a/assets/css/_common/components/pages/breadcrumb.scss b/assets/css/_common/components/pages/breadcrumb.scss new file mode 100644 index 0000000..c0b6f7a --- /dev/null +++ b/assets/css/_common/components/pages/breadcrumb.scss @@ -0,0 +1,21 @@ +ul.breadcrumb { + font-size: $font-size-smallest; + list-style: none; + margin: 1em 0; + padding: 0 2em; + text-align: center; + + li { + display: inline; + } + + li:not(:first-child)::before { + content: '/\00a0'; + font-weight: normal; + padding: .5em; + } + + li:last-child { + font-weight: bold; + } +} diff --git a/assets/css/_common/components/pages/categories.scss b/assets/css/_common/components/pages/categories.scss new file mode 100644 index 0000000..130c58f --- /dev/null +++ b/assets/css/_common/components/pages/categories.scss @@ -0,0 +1,35 @@ +.category-all-page { + .category-all-title { + text-align: center; + } + + .category-all { + margin-top: 20px; + } + + .category-list { + list-style: none; + margin: 0; + padding: 0; + } + + .category-list-item { + margin: 5px 10px; + } + + .category-list-count { + color: $grey; + + &::before { + content: ' ('; + } + + &::after { + content: ') '; + } + } + + .category-list-child { + padding-left: 10px; + } +} diff --git a/assets/css/_common/components/pages/index.scss b/assets/css/_common/components/pages/index.scss new file mode 100644 index 0000000..ee55922 --- /dev/null +++ b/assets/css/_common/components/pages/index.scss @@ -0,0 +1,5 @@ +// Page specific styles +@import 'categories'; +@import 'schedule'; +@import 'breadcrumb'; +@import 'tag-cloud'; diff --git a/assets/css/_common/components/pages/schedule.scss b/assets/css/_common/components/pages/schedule.scss new file mode 100644 index 0000000..808b69d --- /dev/null +++ b/assets/css/_common/components/pages/schedule.scss @@ -0,0 +1,102 @@ +@keyframes dot-flash { + from { + opacity: 1; + transform: scale(1); + } + + to { + opacity: 0; + transform: scale(.8); + } +} + +.event-list { + hr { + background: $black-deep; + margin: 20px 0 45px; + + &::after { + background: $black-deep; + color: white; + content: 'NOW'; + display: inline-block; + font-weight: bold; + padding: 0 5px; + } + } + + .event { + --event-background: #{$black-deep}; + --event-foreground: #{$grey}; + --event-title: white; + background: var(--event-background); + padding: 15px; + + .event-summary { + border-bottom: 0; + color: var(--event-title); + margin: 0; + padding: 0 0 0 35px; + position: relative; + + &::before { + animation: dot-flash 1s alternate infinite ease-in-out; + background: var(--event-title); + left: 0; + margin-top: -6px; + position: absolute; + top: 50%; + @include round-icon(12px); + } + } + + &:nth-of-type(odd) .event-summary::before { + animation-delay: .5s; + } + + &:not(:last-child) { + margin-bottom: 20px; + } + + .event-relative-time { + color: var(--event-foreground); + display: inline-block; + font-size: 12px; + font-weight: normal; + padding-left: 12px; + } + + .event-details { + color: var(--event-foreground); + display: block; + line-height: 18px; + padding: 6px 0 6px 35px; + + &::before { + color: var(--event-foreground); + display: inline-block; + margin-right: 9px; + width: 14px; + @include font-family-icons(); + } + + &.event-location::before { + content: '\f041'; + } + + &.event-duration::before { + content: '\f017'; + } + + &.event-description::before { + content: '\f024'; + } + } + } + + .event-past { + --event-background: #{$whitesmoke}; + --event-foreground: #{$grey-dark}; + --event-title: #{$black-deep}; + } +} diff --git a/assets/css/_common/components/pages/tag-cloud.scss b/assets/css/_common/components/pages/tag-cloud.scss new file mode 100644 index 0000000..7934c6a --- /dev/null +++ b/assets/css/_common/components/pages/tag-cloud.scss @@ -0,0 +1,28 @@ +.tag-cloud { + text-align: center; + + a { + display: inline-block; + margin: 10px; + } +} + +@for $tag-cloud from 0 through 10 { + $tag-cloud-color : mix($tag-cloud-end, $tag-cloud-start, $tag-cloud * 10); + .tag-cloud-#{$tag-cloud} { + border-bottom-color: $tag-cloud-color; + color: $tag-cloud-color; + } +} + +@if hexo-config('darkmode') { + @media (prefers-color-scheme: dark) { + @for $tag-cloud from 0 through 10 { + $tag-cloud-color : mix($tag-cloud-end-dark, $tag-cloud-start-dark, $tag-cloud * 10); + .tag-cloud-#{$tag-cloud} { + border-bottom-color: $tag-cloud-color; + color: $tag-cloud-color; + } + } + } +} diff --git a/assets/css/_common/components/post/index.scss b/assets/css/_common/components/post/index.scss new file mode 100644 index 0000000..a3bc4a2 --- /dev/null +++ b/assets/css/_common/components/post/index.scss @@ -0,0 +1,53 @@ +.rtl { + &.post-body { + p, a, h1, h2, h3, h4, h5, h6, li, ul, ol { + direction: rtl; + font-family: UKIJ Ekran; + } + } + + &.post-title { + font-family: UKIJ Ekran; + } +} + +.post-button { + margin-top: 40px; + text-align: center; +} + +.use-motion { + @if hexo-config('motion.transition.post_block') { + .post-block, .pagination, .comments { + visibility: hidden; + } + } + + @if hexo-config('motion.transition.post_header') { + .post-header { + visibility: hidden; + } + } + + @if hexo-config('motion.transition.post_body') { + .post-body { + visibility: hidden; + } + } + + @if hexo-config('motion.transition.coll_header') { + .collection-header { + visibility: hidden; + } + } +} + +@import 'post-collapse'; +@import 'post-body'; +@import 'post-gallery'; +@import 'post-header'; +@import 'post-nav'; +@import 'post-footer'; +@import 'post-widgets'; +@import 'post-reward'; +@import 'post-followme'; diff --git a/assets/css/_common/components/post/post-body.scss b/assets/css/_common/components/post/post-body.scss new file mode 100644 index 0000000..0f96b5d --- /dev/null +++ b/assets/css/_common/components/post/post-body.scss @@ -0,0 +1,79 @@ +.post-body { + font-family: $font-family-posts; + @include word-wrap(); + + @include desktop-large() { + font-size: $font-size-large; + } + + @include desktop() { + text-align: unquote(hexo-config('text_align.desktop')); + } + + @include tablet-mobile() { + text-align: unquote(hexo-config('text_align.mobile')); + } + + h1, h2, h3, h4, h5, h6 { + // Supported plugins: hexo-renderer-markdown-it hexo-renderer-marked + .header-anchor, .headerlink { + border-bottom-style: none; + color: inherit; + float: right; + font-size: $font-size-small; + margin-left: 10px; + opacity: 0; + + &::before { + @include font-family-icons('\f0c1'); + } + } + + &:hover { + .header-anchor, .headerlink { + opacity: .5; + + &:hover { + opacity: 1; + } + } + } + } + + .exturl .fa { + font-size: $font-size-small; + margin-left: 4px; + } + + // For fancybox and pandoc + .image-caption, img + figcaption, .fancybox + figcaption { + color: $grey-dark; + font-size: $font-size-small; + font-weight: bold; + line-height: 1; + margin: -15px auto 15px; + text-align: center; + } + + iframe, img, video, embed { + margin-bottom: 20px; + } + + .video-container { + height: 0; + margin-bottom: 20px; + overflow: hidden; + padding-top: 75%; + position: relative; + width: 100%; + + iframe, object, embed { + height: 100%; + left: 0; + margin: 0; + position: absolute; + top: 0; + width: 100%; + } + } +} diff --git a/assets/css/_common/components/post/post-collapse.scss b/assets/css/_common/components/post/post-collapse.scss new file mode 100644 index 0000000..607a778 --- /dev/null +++ b/assets/css/_common/components/post/post-collapse.scss @@ -0,0 +1,109 @@ +.posts-collapse .post-content { + margin-bottom: $posts-collapse-margin; + margin-left: $posts-collapse-margin; + position: relative; + + @include mobile() { + margin-left: $posts-collapse-margin-mobile; + margin-right: $posts-collapse-margin-mobile; + } + + .collection-title { + font-size: $font-size-large; + position: relative; + + &::before { + background: $grey-dark; + border: 1px solid white; + margin-left: -6px; + margin-top: -4px; + position: absolute; + top: 50%; + @include round-icon(10px); + } + } + + .collection-year { + font-size: $font-size-largest; + font-weight: bold; + margin: 60px 0; + position: relative; + + &::before { + background: $grey; + margin-left: -4px; + margin-top: -4px; + position: absolute; + top: 50%; + @include round-icon(8px); + } + } + + .collection-header { + display: block; + margin-left: 20px; + + small { + color: $grey; + margin-left: 5px; + } + } + + .post-header { + border-bottom: 1px dashed $grey-light; + // 2px is equal to half the width of .posts-collapse::before + margin: 30px 2px 0; + padding-left: 15px; + position: relative; + transition: border $transition-ease; + + &::before { + background: $grey; + border: 1px solid white; + left: -6px; + position: absolute; + top: $font-size-smallest; + transition: background $transition-ease; + @include round-icon(6px); + } + + &:hover { + border-bottom-color: $grey-dim; + + &::before { + background: $black-deep; + } + } + } + + .post-meta-container { + display: inline; + font-size: $font-size-smallest; + margin-right: 10px; + } + + .post-title { + display: inline; + + a { + border-bottom: 0; + color: var(--link-color); + } + + .fa-external-link-alt { + font-size: $font-size-small; + margin-left: 5px; + } + } + + &::before { + background: $whitesmoke; + content: ' '; + height: 100%; + margin-left: -2px; + position: absolute; + // To do: 1.25em is inaccurate when .collection-title has line breaks on mobile + top: 1.25em; + width: 4px; + } +} diff --git a/assets/css/_common/components/post/post-followme.scss b/assets/css/_common/components/post/post-followme.scss new file mode 100644 index 0000000..7974b3f --- /dev/null +++ b/assets/css/_common/components/post/post-followme.scss @@ -0,0 +1,35 @@ +@if hexo-config('follow_me') { + .followme { + color: $grey; + padding: 1em 1.5em; + text-align: center; + @include post-card(); + + .social-list { + @include flex-wrap(); + + .social-item { + margin: .5em 2em; + + @include tablet-mobile() { + margin: .5em .75em; + } + } + + .social-link { + border: 0; + display: inline-block; + text-align: center; + + .icon { + font-size: 1.75em; + } + + .label { + display: block; + font-size: 14px; + } + } + } + } +} diff --git a/assets/css/_common/components/post/post-footer.scss b/assets/css/_common/components/post/post-footer.scss new file mode 100644 index 0000000..2726dab --- /dev/null +++ b/assets/css/_common/components/post/post-footer.scss @@ -0,0 +1,41 @@ +// Flexbox layout makes it possible to reorder the child +// elements of .post-footer through the `order` CSS property +// Fix issue #16 +// To do: use `gap` instead of `margin` +// See https://caniuse.com/flexbox-gap +.post-footer { + @include flex-column(); +} + +.post-eof { + background: $grey-light; + height: 1px; + margin: $post-eof-margin-top auto $post-eof-margin-bottom; + width: 8%; + + .post-block:last-of-type & { + display: none; + } +} + +@if hexo-config('creative_commons.post') { + .post-copyright ul { + list-style: none; + padding: .5em 1em; + @include post-card(); + } +} + +.post-tags { + margin-top: 40px; + text-align: center; + + a { + display: inline-block; + font-size: $font-size-smaller; + + &:not(:last-child) { + margin-right: 10px; + } + } +} diff --git a/assets/css/_common/components/post/post-gallery.scss b/assets/css/_common/components/post/post-gallery.scss new file mode 100644 index 0000000..a4240d7 --- /dev/null +++ b/assets/css/_common/components/post/post-gallery.scss @@ -0,0 +1,33 @@ +.post-gallery { + display: flex; + min-height: 200px; + + .post-gallery-image { + flex: 1; + + &:not(:first-child) { + clip-path: polygon(40px 0, 100% 0, 100% 100%, 0 100%); + margin-left: -20px; + } + + &:not(:last-child) { + margin-right: -20px; + } + + img { + height: 100%; + object-fit: cover; + // Override darkmode image opacity. + opacity: 1; + width: 100%; + } + } +} + +.posts-expand .post-gallery { + margin-bottom: 60px; +} + +.posts-collapse .post-gallery { + margin: 15px 0; +} diff --git a/assets/css/_common/components/post/post-header.scss b/assets/css/_common/components/post/post-header.scss new file mode 100644 index 0000000..b3872d2 --- /dev/null +++ b/assets/css/_common/components/post/post-header.scss @@ -0,0 +1,120 @@ +.posts-expand .post-header { + font-size: $font-size-large; + margin-bottom: 60px; + text-align: center; +} + +.posts-expand .post-title { + font-size: $font-size-largest; + font-weight: normal; + margin: initial; + @include word-wrap(); + + @if hexo-config('post_edit.enable') { + .post-edit-link { + border-bottom: 0; + color: $grey; + float: right; + font-size: $font-size-larger; + margin-left: -1.2em; + transition: color $transition-ease-in; + + @include mobile-small() { + margin-left: initial; + } + + &:hover { + color: $sidebar-highlight; + } + } + } +} + +.posts-expand .post-title-link { + border-bottom: 0; + color: var(--link-color); + display: inline-block; + position: relative; + + &::before { + background: var(--link-color); + bottom: 0; + content: ''; + height: 2px; + // Fix issue #75 + left: 0; + position: absolute; + transform: scaleX(0); + transition: transform $transition-ease; + width: 100%; + } + + &:hover::before { + transform: scaleX(1); + } + + .fa-external-link-alt { + font-size: $font-size-small; + margin-left: 5px; + } +} + +.post-sticky-flag { + display: inline-block; + // Fix issue #80 #140 + margin-right: 8px; + transform: rotate(30deg); +} + +.posts-expand .post-meta-container { + color: $grey-dark; + font-family: $font-family-posts; + font-size: $font-size-smallest; + margin-top: 3px; + + .post-description { + font-size: $font-size-small; + margin-top: 2px; + } + + time { + border-bottom: 1px dashed $grey-dark; + } +} + +// Flexbox layout makes it possible to reorder the child +// elements of .post-meta through the `order` CSS property +.post-meta { + @include flex-wrap(); +} + +// .post-meta-item exists in .post-meta and footer +:not(.post-meta-break) + .post-meta-item::before { + content: '|'; + margin: 0 .5em; +} + +.post-meta-item-icon { + margin-right: 3px; +} + +.post-meta-item-text { + @if not hexo-config('post_meta.item_text') { + display: none; + } + + @include tablet-mobile() { + display: none; + } +} + +.post-meta-break { + flex-basis: 100%; + height: 0; +} + +@if hexo-config('busuanzi_count.enable') and hexo-config('busuanzi_count.post_views') { + #busuanzi_container_page_pv { + display: none; + } +} diff --git a/assets/css/_common/components/post/post-nav.scss b/assets/css/_common/components/post/post-nav.scss new file mode 100644 index 0000000..1f14593 --- /dev/null +++ b/assets/css/_common/components/post/post-nav.scss @@ -0,0 +1,41 @@ +.post-nav { + border-top: 1px solid $gainsboro; + display: flex; + gap: 30px; + justify-content: space-between; + margin-top: 1em; + padding: 10px 5px 0; +} + +.post-nav-item { + flex: 1; + + a { + border-bottom: 0; + display: block; + font-size: $font-size-small; + line-height: 1.6; + + &:active { + top: 2px; + } + } + + .fa { + font-size: $font-size-smallest; + } + + &:first-child { + .fa { + margin-right: 5px; + } + } + + &:last-child { + text-align: right; + + .fa { + margin-left: 5px; + } + } +} diff --git a/assets/css/_common/components/post/post-reward.scss b/assets/css/_common/components/post/post-reward.scss new file mode 100644 index 0000000..16fdc12 --- /dev/null +++ b/assets/css/_common/components/post/post-reward.scss @@ -0,0 +1,56 @@ +.reward-container { + margin: $post-card-margin; + padding: 1em 0; + text-align: center; + + button { + @include button($sidebar-highlight); + border: 2px solid $sidebar-highlight; + border-radius: 2px; + outline: 0; + transition: all $transition-ease; + vertical-align: text-top; + } +} + +.post-reward { + display: none; + padding-top: 20px; + + &.active { + display: block; + } + + div { + display: inline-block; + + span { + display: block; + } + + @if hexo-config('reward_settings.animation') { + &:hover span { + animation: next-roll .1s infinite linear; + // The animation may affect :hover of img in dark mode + pointer-events: none; + } + } + } + + img { + display: inline-block; + margin: .8em 2em 0; + max-width: 100%; + width: 180px; + } +} + +@keyframes next-roll { + from { + transform: rotateZ(30deg); + } + + to { + transform: rotateZ(-30deg); + } +} diff --git a/assets/css/_common/components/post/post-widgets.scss b/assets/css/_common/components/post/post-widgets.scss new file mode 100644 index 0000000..eea67c8 --- /dev/null +++ b/assets/css/_common/components/post/post-widgets.scss @@ -0,0 +1,20 @@ +.post-widgets { + border-top: 1px solid $gainsboro; + margin-top: 15px; + text-align: center; +} + +.wpac-rating-container { + height: 20px; + line-height: 20px; + margin-top: 10px; + padding-top: 6px; + text-align: center; +} + +.social-like { + display: flex; + font-size: $font-size-small; + justify-content: center; + text-align: center; +} diff --git a/assets/css/_common/components/reading-progress.scss b/assets/css/_common/components/reading-progress.scss new file mode 100644 index 0000000..a2bcb13 --- /dev/null +++ b/assets/css/_common/components/reading-progress.scss @@ -0,0 +1,27 @@ +@if hexo-config('reading_progress.enable') { + .reading-progress-bar { + --progress: 0; + background: convert(hexo-config('reading_progress.color')); + height: convert(hexo-config('reading_progress.height')); + position: fixed; + z-index: $zindex-5; + + @if hexo-config('reading_progress.reversed') { + width: calc(100% - var(--progress)); + } @else { + width: var(--progress); + } + + @if hexo-config('reading_progress.start_at') == 'right' { + right: 0; + } @else { + left: 0; + } + + @if hexo-config('reading_progress.position') == 'bottom' { + bottom: 0; + } @else { + top: 0; + } + } +} diff --git a/assets/css/_common/components/third-party/disqusjs.styl b/assets/css/_common/components/third-party/disqusjs.styl new file mode 100644 index 0000000..1662456 --- /dev/null +++ b/assets/css/_common/components/third-party/disqusjs.styl @@ -0,0 +1,39 @@ +if (hexo-config('disqusjs.enable') and hexo-config('darkmode')) { + @media (prefers-color-scheme:dark) { + html #dsqjs a { + color: var(--link-color) + } + + html #dsqjs a:focus,html #dsqjs a:hover { + color: var(--link-hover-color) + } + + html #dsqjs .dsqjs-nav,html #dsqjs footer { + border-color: var(--card-bg-color) + } + + html #dsqjs .dsqjs-load-more,html #dsqjs .dsqjs-load-more:hover,html #dsqjs .dsqjs-nav-tab,html #dsqjs .dsqjs-no-comment,html #dsqjs .dsqjs-post-content { + color: var(--text-color) + } + + html #dsqjs .dsqjs-order-label { + background-color: #3e4b5e + } + + html #dsqjs .dsqjs-order-radio:checked+.dsqjs-order-label { + background-color: var(--content-bg-color) + } + + html #dsqjs .dsqjs-tab-active>span:after { + background-color: #2e9fff!important + } + + html #dsqjs .dsqjs-footer,html #dsqjs .dsqjs-meta { + color: var(--text-color) + } + + html #dsqjs .dsqjs-post-body blockquote { + border-color: var(--content-bg-color) + } + } +} diff --git a/assets/css/_common/components/third-party/gitalk.scss b/assets/css/_common/components/third-party/gitalk.scss new file mode 100644 index 0000000..52f7934 --- /dev/null +++ b/assets/css/_common/components/third-party/gitalk.scss @@ -0,0 +1,9 @@ +@if hexo-config('gitalk.enable') { + .gt-header a, .gt-comments a, .gt-popup a { + border-bottom: 0; + } + + .gt-container .gt-popup .gt-action.is--active::before { + top: .7em; + } +} diff --git a/assets/css/_common/components/third-party/gitter.styl b/assets/css/_common/components/third-party/gitter.styl new file mode 100644 index 0000000..ced2490 --- /dev/null +++ b/assets/css/_common/components/third-party/gitter.styl @@ -0,0 +1,7 @@ +if (hexo-config('gitter.enable')) { + .gitter-open-chat-button { + $alignment = sidebar-toggle-alignment(false); + {$alignment[0]}: auto !important; + {$alignment[1]}: 10px !important; + } +} diff --git a/assets/css/_common/components/third-party/index.scss b/assets/css/_common/components/third-party/index.scss new file mode 100644 index 0000000..101dc72 --- /dev/null +++ b/assets/css/_common/components/third-party/index.scss @@ -0,0 +1,18 @@ +@import 'disqusjs'; +@import 'gitalk'; +@import 'utterances'; +@import 'search'; +@import 'related-posts'; +@import 'math'; +@import 'gitter'; + +.use-motion .animated { + // Fix issue #48 #55 + animation-fill-mode: none; + // Fix issue #46 .animated in .sidebar + visibility: inherit; +} + +.use-motion .sidebar .animated { + animation-fill-mode: both; +} diff --git a/assets/css/_common/components/third-party/math.scss b/assets/css/_common/components/third-party/math.scss new file mode 100644 index 0000000..87bb78b --- /dev/null +++ b/assets/css/_common/components/third-party/math.scss @@ -0,0 +1,9 @@ +@if hexo-config('math.mathjax.enable') { + mjx-container[jax='CHTML'][display='true'], .has-jax { + overflow: auto hidden; + } + + mjx-container[display='true'] + br { + display: none; + } +} diff --git a/assets/css/_common/components/third-party/related-posts.scss b/assets/css/_common/components/third-party/related-posts.scss new file mode 100644 index 0000000..0c16dad --- /dev/null +++ b/assets/css/_common/components/third-party/related-posts.scss @@ -0,0 +1,23 @@ +@if hexo-config('related_posts.enable') { + .popular-posts-header { + border-bottom: 1px solid $gainsboro; + font-size: $font-size-large; + margin-bottom: 10px; + margin-top: $post-eof-margin-bottom; + } + + .popular-posts { + padding: 0; + + .popular-posts-item { + margin-left: 2em; + + .popular-posts-title { + font-size: $font-size-small; + font-weight: normal; + line-height: $line-height-base * 1.2; + margin: 0; + } + } + } +} diff --git a/assets/css/_common/components/third-party/search.scss b/assets/css/_common/components/third-party/search.scss new file mode 100644 index 0000000..4748079 --- /dev/null +++ b/assets/css/_common/components/third-party/search.scss @@ -0,0 +1,179 @@ +@if hexo-config('local_search.enable') or hexo-config('algolia_search.enable') { + .search-active { + overflow: hidden; + } + + .search-pop-overlay { + background: rgba(0, 0, 0, 0); + display: flex; + height: 100%; + left: 0; + position: fixed; + top: 0; + transition: visibility .4s, background .4s; + visibility: hidden; + width: 100%; + z-index: $zindex-4; + + .search-active & { + background: rgba(0, 0, 0, .3); + visibility: visible; + } + } + + .search-popup { + background: var(--card-bg-color); + border-radius: 5px; + height: 80%; + margin: auto; + transform: scale(0); + transition: transform .4s; + width: 700px; + + .search-active & { + transform: scale(1); + } + + @include mobile() { + border-radius: 0; + height: 100%; + width: 100%; + } + + .search-icon, .popup-btn-close { + color: $grey-dark; + font-size: 18px; + padding: 0 10px; + } + + .popup-btn-close { + cursor: pointer; + + &:hover .fa { + color: $black-deep; + } + } + + .search-header { + background: $gainsboro; + if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + background: $grey-dim; + } + } + border-top-left-radius: 5px; + border-top-right-radius: 5px; + display: flex; + padding: 5px; + } + + input.search-input { + background: transparent; + border: 0; + outline: 0; + width: 100%; + + &::-webkit-search-cancel-button { + display: none; + } + } + + .search-result-container { + height: calc(100% - 55px); + overflow: auto; + padding: 5px 25px; + + hr { + margin: 5px 0 10px; + + &:first-child { + display: none; + } + } + } + + .search-result-list { + margin: 0 5px; + padding: 0; + } + + a.search-result-title { + font-weight: bold; + } + + p.search-result { + border-bottom: 1px dashed $grey-light; + padding: 5px 0; + } + } +} + +@if hexo-config('algolia_search.enable') { + .search-input-container { + flex-grow: 1; + + form { + padding: 2px; + } + } + + .search-stats { + align-items: center; + display: flex; + justify-content: space-between; + + img { + height: 1em; + margin: 0; + } + } + + .algolia-pagination { + // Override default style of ul + margin: 40px 0; + opacity: 1; + padding: 0; + + .pagination-item { + display: inline-block; + } + + .current .page-number { + @extend %page-number-current; + cursor: default; + } + + .disabled-item { + visibility: hidden; + } + } +} + +@if hexo-config('local_search.enable') { + .search-popup { + .search-input-container { + flex-grow: 1; + padding: 2px; + } + + .no-result { + display: flex; + } + + .search-result-list { + width: 100%; + } + + .search-result-icon { + color: $grey-light; + margin: auto; + } + } + + mark.search-keyword { + background: transparent; + border-bottom: 1px dashed $red; + color: $red; + font-weight: bold; + } +} diff --git a/assets/css/_common/components/third-party/utterances.scss b/assets/css/_common/components/third-party/utterances.scss new file mode 100644 index 0000000..7dd3c92 --- /dev/null +++ b/assets/css/_common/components/third-party/utterances.scss @@ -0,0 +1,5 @@ +@if hexo-config('utterances.enable') { + .utterances { + max-width: unset; + } +} diff --git a/assets/css/_common/outline/footer/index.scss b/assets/css/_common/outline/footer/index.scss new file mode 100644 index 0000000..4cba027 --- /dev/null +++ b/assets/css/_common/outline/footer/index.scss @@ -0,0 +1,100 @@ +// Footer Section +// -------------------------------------------------- +.footer { + color: $grey-dark; + font-size: $font-size-small; + padding: 20px 0; + + &.footer-fixed { + bottom: 0; + left: 0; + position: absolute; + right: 0; + } +} + +// Flexbox layout makes it possible to reorder the child +// elements of .footer-inner through the `order` CSS property +.footer-inner { + box-sizing: border-box; + text-align: center; + @include flex-column(); + @include main-container(); +} + +.use-motion { + .footer { + opacity: 0; + } +} + +@keyframes icon-animate { + 0%, 100% { + transform: scale(1); + } + + 10%, 30% { + transform: scale(.9); + } + + 20%, 40%, 60%, 80% { + transform: scale(1.1); + } + + 50%, 70% { + transform: scale(1.1); + } +} + +.languages { + display: inline-block; + font-size: $font-size-large; + position: relative; + + .lang-select-label span { + margin: 0 .5em; + } + + .lang-select { + height: 100%; + left: 0; + opacity: 0; + position: absolute; + top: 0; + width: 100%; + } +} + +.with-love { + color: hexo-config('footer.icon.color'); + display: inline-block; + margin: 0 5px; + + @if hexo-config('footer.icon.animated') { + animation: icon-animate 1.33s ease-in-out infinite; + } +} + +@if hexo-config('footer.beian.enable') and hexo-config('footer.beian.gongan_icon_url') { + .beian img { + display: inline-block; + margin: 0 3px; + vertical-align: middle; + } +} + +@if hexo-config('busuanzi_count.enable') { + .busuanzi-count { + @if hexo-config('busuanzi_count.total_visitors') { + #busuanzi_container_site_uv { + display: none; + } + } + + @if hexo-config('busuanzi_count.total_views') { + #busuanzi_container_site_pv { + display: none; + } + } + } +} diff --git a/assets/css/_common/outline/header/bookmark.scss b/assets/css/_common/outline/header/bookmark.scss new file mode 100644 index 0000000..c7a7587 --- /dev/null +++ b/assets/css/_common/outline/header/bookmark.scss @@ -0,0 +1,24 @@ +@if hexo-config('bookmark.enable') { + .book-mark-link { + border-bottom: 0; + position: fixed; + top: -10px; + transition: top .3s; + @include sidebar-toggle-position(true); + + @include tablet-mobile() { + display: none; + } + + &::before { + color: convert(hexo-config('bookmark.color')); + font-size: 32px; + line-height: 1; + @include font-family-icons('\f02e'); + } + } + + .book-mark-link:hover, .book-mark-link-fixed { + top: -2px; + } +} diff --git a/assets/css/_common/outline/header/github-banner.scss b/assets/css/_common/outline/header/github-banner.scss new file mode 100644 index 0000000..82c5203 --- /dev/null +++ b/assets/css/_common/outline/header/github-banner.scss @@ -0,0 +1,59 @@ +@if hexo-config('github_banner.enable') { + @keyframes octocat-wave { + 0%, 100% { + transform: rotate(0); + } + + 20%, 60% { + transform: rotate(-25deg); + } + + 40%, 80% { + transform: rotate(10deg); + } + } + + .github-corner { + :hover .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + + svg { + color: white; + fill: var(--theme-color); + position: absolute; + right: 0; + top: 0; + z-index: $zindex-0; + } + + @include tablet-mobile() { + @if hexo-config('local_search.enable') or hexo-config('algolia_search.enable') { + display: none; + } + + svg { + @if ($scheme == 'Pisces') or ($scheme == 'Gemini') { + color: var(--theme-color); + fill: white; + } + } + + .github-corner:hover .octo-arm { + animation: none; + } + + .github-corner .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + } + + @if $scheme == 'Mist' { + @include mobile() { + svg { + top: inherit; + } + } + } + } +} diff --git a/assets/css/_common/outline/header/index.scss b/assets/css/_common/outline/header/index.scss new file mode 100644 index 0000000..3326bd6 --- /dev/null +++ b/assets/css/_common/outline/header/index.scss @@ -0,0 +1,38 @@ +// Header Section +// -------------------------------------------------- +.headband { + background: $headband-bg; + height: $headband-height; + + @include tablet-mobile() { + display: none; + } +} + +// Fix issue #521 +header.header { + background: $head-bg; +} + +.header-inner { + @include main-container(); +} + +.site-brand-container { + display: flex; + flex-shrink: 0; + padding: 0 10px; +} + +.use-motion { + header.header, .site-brand-container .toggle { + opacity: 0; + } +} + +@import 'site-meta'; +@import 'site-nav'; +@import 'menu'; + +@import 'bookmark'; +@import 'github-banner'; diff --git a/assets/css/_common/outline/header/menu.scss b/assets/css/_common/outline/header/menu.scss new file mode 100644 index 0000000..495a7dd --- /dev/null +++ b/assets/css/_common/outline/header/menu.scss @@ -0,0 +1,56 @@ +// Menu +// -------------------------------------------------- +.menu { + margin: 0; + padding: 1em 0; + text-align: center; +} + +.menu-item { + display: inline-block; + list-style: none; + margin: 0 10px; + + @include mobile() { + display: block; + margin-top: 10px; + + &.menu-item-search { + display: none; + } + } + + a { + border-bottom: 0; + display: block; + font-size: $font-size-smaller; + transition: border-color $transition-ease; + + &:hover, &.menu-item-active { + background: var(--menu-item-bg-color); + } + } + + .fa, .fab, .far, .fas { + margin-right: 8px; + } + + .badge { + display: inline-block; + font-weight: bold; + line-height: 1; + margin-left: .35em; + margin-top: .35em; + text-align: center; + white-space: nowrap; + + @include mobile() { + float: right; + margin-left: 0; + } + } +} + +.use-motion .menu-item { + visibility: hidden; +} diff --git a/assets/css/_common/outline/header/site-meta.scss b/assets/css/_common/outline/header/site-meta.scss new file mode 100644 index 0000000..b79d678 --- /dev/null +++ b/assets/css/_common/outline/header/site-meta.scss @@ -0,0 +1,49 @@ +.site-meta { + flex-grow: 1; + text-align: center; + + @include mobile() { + text-align: center; + } +} + +.custom-logo-image { + margin-top: 20px; + + @include tablet-mobile() { + display: none; + } +} + +.brand { + border-bottom: 0; + color: var(--brand-color); + display: inline-block; + padding: 0 40px; + + &:hover { + color: var(--brand-hover-color); + } +} + +.site-title { + font-family: $font-family-logo; + font-size: $font-size-title; + font-weight: normal; + line-height: 1.5; + margin: 0; +} + +.site-subtitle { + color: $subtitle-color; + font-size: $font-size-subtitle; + margin: 10px 0; +} + +.use-motion { + .site-title, .site-subtitle, .custom-logo-image { + opacity: 0; + position: relative; + top: -10px; + } +} diff --git a/assets/css/_common/outline/header/site-nav.scss b/assets/css/_common/outline/header/site-nav.scss new file mode 100644 index 0000000..9c744ad --- /dev/null +++ b/assets/css/_common/outline/header/site-nav.scss @@ -0,0 +1,24 @@ +.site-nav-toggle, .site-nav-right { + display: none; + + @include mobile() { + @include flex-column(); + } + + .toggle { + color: var(--text-color); + padding: 10px; + width: 22px; + + .toggle-line { + background: var(--text-color); + border-radius: 1px; + } + } +} + +.site-nav { + @include mobile() { + @include site-nav-hide-by-default(); + } +} diff --git a/assets/css/_common/outline/index.scss b/assets/css/_common/outline/index.scss new file mode 100644 index 0000000..fd6fc19 --- /dev/null +++ b/assets/css/_common/outline/index.scss @@ -0,0 +1,5 @@ +@import 'header'; +@import 'sidebar'; +@import 'footer'; + +@import 'mobile'; diff --git a/assets/css/_common/outline/mobile.scss b/assets/css/_common/outline/mobile.scss new file mode 100644 index 0000000..71502c9 --- /dev/null +++ b/assets/css/_common/outline/mobile.scss @@ -0,0 +1,85 @@ +/* +// < 767px +@include mobile() { + +} +*/ + +@if hexo-config('mobile_layout_economy') { + @include mobile-small() { + // For Pisces & Gemini schemes only wider width (remove main blocks in Gemini). + .main-inner { + padding: initial !important; + } + + // For all schemes wider width. + .posts-expand { + .post-header { + margin-bottom: 10px !important; + } + } + + .post-block { + margin-top: initial !important; + // Inside posts blocks content padding (default 40px). + padding: $content-mobile-padding 18px $content-mobile-padding !important; + } + + .post-body { + // For headers narrow width. + h1, h2, h3, h4, h5, h6 { + margin: 20px 0 8px; + } + + // Rewrite paddings & margins inside tags. + .note, .tabs .tab-content .tab-pane { + h1, h2, h3, h4, h5, h6 { + margin: 0 5px; + } + } + + // For paragraphs narrow width. + > p { + margin: 0 0 10px; + } + + // Rewrite paddings & margins inside tags. + .note > p, .tabs .tab-content .tab-pane > p { + padding: 0 5px; + } + + img, video { + margin-bottom: 10px !important; + } + + .note { + margin-bottom: 10px !important; + padding: 10px !important; + + @if hexo-config('note.icons') { + &:not(.no-icon) { + padding-left: 35px !important; + } + } + } + + .tabs .tab-content .tab-pane { + padding: 10px 10px 0 !important; + } + } + + .post-eof { + margin: 40px auto 20px !important; + } + + .pagination { + margin-top: 40px; + } + } +} +/* +// < 413px +@include mobile-smallest() { + +} +*/ diff --git a/assets/css/_common/outline/sidebar/index.scss b/assets/css/_common/outline/sidebar/index.scss new file mode 100644 index 0000000..d74ca3f --- /dev/null +++ b/assets/css/_common/outline/sidebar/index.scss @@ -0,0 +1,38 @@ +.sidebar-inner { + color: $grey-dark; + // Init Sidebar & TOC inner dimensions on all pages and for all schemes. + $offset : if(($scheme == 'Pisces') or ($scheme == 'Gemini'), $sidebar-offset, $sidebar-padding); + max-height: calc(100vh - #{$offset * 2}); + padding: $sidebar-padding 10px; + text-align: center; + @include flex-column(); +} + +.site-overview-item:not(:first-child) { + margin-top: 10px; +} + +.cc-license { + .cc-opacity { + border-bottom: 0; + opacity: .7; + + &:hover { + opacity: .9; + } + } + + img { + display: inline-block; + } +} + +@import 'sidebar-author'; +@import 'sidebar-author-links'; +@import 'sidebar-button'; +@import 'sidebar-blogroll'; +@import 'sidebar-dimmer'; +@import 'sidebar-nav'; +@import 'sidebar-toggle'; +@import 'sidebar-toc'; +@import 'site-state'; diff --git a/assets/css/_common/outline/sidebar/sidebar-author-links.scss b/assets/css/_common/outline/sidebar/sidebar-author-links.scss new file mode 100644 index 0000000..0ad756e --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-author-links.scss @@ -0,0 +1,11 @@ +.links-of-author { + a { + font-size: $font-size-smaller; + } + + @if not hexo-config('social_icons.icons_only') { + .fa, .fab, .far, .fas { + margin-right: 2px; + } + } +} diff --git a/assets/css/_common/outline/sidebar/sidebar-author.scss b/assets/css/_common/outline/sidebar/sidebar-author.scss new file mode 100644 index 0000000..7eb67ec --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-author.scss @@ -0,0 +1,29 @@ +.site-author-image { + border: $site-author-image-border-width solid $site-author-image-border-color; + max-width: $site-author-image-width; + padding: 2px; + + @if hexo-config('avatar.rounded') { + border-radius: 50%; + } + + @if hexo-config('avatar.rotated') { + transition: transform 1s ease-out; + + &:hover { + transform: rotateZ(360deg); + } + } +} + +.site-author-name { + color: $site-author-name-color; + font-weight: $site-author-name-weight; + margin: $site-author-name-margin; +} + +.site-description { + color: $site-description-color; + font-size: $site-description-font-size; + margin-top: $site-description-margin-top; +} diff --git a/assets/css/_common/outline/sidebar/sidebar-blogroll.scss b/assets/css/_common/outline/sidebar/sidebar-blogroll.scss new file mode 100644 index 0000000..ec51087 --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-blogroll.scss @@ -0,0 +1,15 @@ +.links-of-blogroll { + font-size: $font-size-smaller; +} + +.links-of-blogroll-title { + font-size: $font-size-small; + font-weight: 600; + margin-top: 0; +} + +.links-of-blogroll-list { + list-style: none; + margin: 0; + padding: 0; +} diff --git a/assets/css/_common/outline/sidebar/sidebar-button.scss b/assets/css/_common/outline/sidebar/sidebar-button.scss new file mode 100644 index 0000000..2cf4ada --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-button.scss @@ -0,0 +1,15 @@ +.sidebar .sidebar-button { + &:not(:first-child) { + margin-top: 15px; + } + + button { + @include button($orange); + border: 1px solid $orange; + border-radius: 4px; + + .fa, .fab, .far, .fas { + margin-right: 5px; + } + } +} diff --git a/assets/css/_common/outline/sidebar/sidebar-dimmer.scss b/assets/css/_common/outline/sidebar/sidebar-dimmer.scss new file mode 100644 index 0000000..18e2bf9 --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-dimmer.scss @@ -0,0 +1,24 @@ +.sidebar-dimmer { + display: none; +} + +@include tablet-mobile() { + .sidebar-dimmer { + background: black; + display: block; + height: 100%; + left: 0; + opacity: 0; + position: fixed; + top: 0; + transition: visibility .4s, opacity .4s; + visibility: hidden; + width: 100%; + z-index: $zindex-1; + + .sidebar-active & { + opacity: .7; + visibility: visible; + } + } +} diff --git a/assets/css/_common/outline/sidebar/sidebar-nav.scss b/assets/css/_common/outline/sidebar/sidebar-nav.scss new file mode 100644 index 0000000..1f137bb --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-nav.scss @@ -0,0 +1,57 @@ +// Sidebar Navigation +.sidebar-nav { + display: none; + margin: 0; + padding-bottom: 20px; + padding-left: 0; + + .sidebar-nav-active & { + display: block; + } + + li { + border-bottom: 1px solid transparent; + color: $sidebar-nav-color; + cursor: pointer; + display: inline-block; + font-size: $font-size-small; + + &.sidebar-nav-overview { + margin-left: 10px; + } + + &:hover { + color: $sidebar-nav-hover-color; + } + } +} + +.sidebar-toc-active .sidebar-nav-toc, .sidebar-overview-active .sidebar-nav-overview { + border-bottom-color: $sidebar-highlight; + color: $sidebar-highlight; + + &:hover { + color: $sidebar-highlight; + } +} + +// Need for Sidebar/TOC inner scrolling if content taller then viewport. +.sidebar-panel-container { + flex: 1; + overflow-x: hidden; + overflow-y: auto; +} + +.sidebar-panel { + display: none; +} + +.sidebar-overview-active .site-overview-wrap { + // Flexbox layout makes it possible to reorder the child + // elements of .site-overview-item through the `order` CSS property + @include flex-column(); +} + +.sidebar-toc-active .post-toc-wrap { + display: block; +} diff --git a/assets/css/_common/outline/sidebar/sidebar-toc.scss b/assets/css/_common/outline/sidebar/sidebar-toc.scss new file mode 100644 index 0000000..86b0eb8 --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-toc.scss @@ -0,0 +1,61 @@ +@if hexo-config('toc.enable') { + .post-toc { + font-size: $font-size-small; + + ol { + list-style: none; + margin: 0; + padding: 0 2px 5px 10px; + text-align: left; + + > ol { + padding-left: 0; + } + + a { + transition: all $transition-ease; + } + } + + .nav-item { + line-height: 1.8; + overflow: hidden; + text-overflow: ellipsis; + + @if not hexo-config('toc.wrap') { + white-space: nowrap; + } + } + + .nav { + .nav-child { + display: if(hexo-config('toc.expand_all'), block, none); + } + + .active > .nav-child { + display: block; + } + + .active-current > .nav-child { + display: block; + + > .nav-item { + display: block; + } + } + + .active > a { + border-bottom-color: $sidebar-highlight; + color: $sidebar-highlight; + } + + .active-current > a { + color: $sidebar-highlight; + + &:hover { + color: $sidebar-highlight; + } + } + } + } +} diff --git a/assets/css/_common/outline/sidebar/sidebar-toggle.scss b/assets/css/_common/outline/sidebar/sidebar-toggle.scss new file mode 100644 index 0000000..0fafdea --- /dev/null +++ b/assets/css/_common/outline/sidebar/sidebar-toggle.scss @@ -0,0 +1,21 @@ +.sidebar-toggle { + bottom: 45px; + height: 12px; + padding: 6px 5px; + width: 14px; + @include sidebar-toggle(); +} + +.sidebar-toggle:hover .toggle-line { + background: $sidebar-highlight; +} + +@media (any-hover: hover) { + body:not(.sidebar-active) .sidebar-toggle:hover { + @include toggle-arrow(hexo-config('sidebar.position')); + } +} + +.sidebar-active .sidebar-toggle { + @include toggle-close(hexo-config('sidebar.position')); +} diff --git a/assets/css/_common/outline/sidebar/site-state.scss b/assets/css/_common/outline/sidebar/site-state.scss new file mode 100644 index 0000000..123b049 --- /dev/null +++ b/assets/css/_common/outline/sidebar/site-state.scss @@ -0,0 +1,28 @@ +@if hexo-config('site_state') { + .site-state { + @include flex-wrap(); + line-height: 1.4; + } + + .site-state-item { + // Fix issue #103 + // The click area of the link becomes smaller + padding: 0 15px; + + a { + border-bottom: 0; + display: block; + } + } + + .site-state-item-count { + display: block; + font-size: $site-state-item-count-font-size; + font-weight: 600; + } + + .site-state-item-name { + color: $site-state-item-name-color; + font-size: $site-state-item-name-font-size; + } +} diff --git a/assets/css/_common/scaffolding/base.scss b/assets/css/_common/scaffolding/base.scss new file mode 100644 index 0000000..610ead2 --- /dev/null +++ b/assets/css/_common/scaffolding/base.scss @@ -0,0 +1,99 @@ +::selection { + background: $selection-bg; + color: $selection-color; +} + +html, body { + height: 100%; +} + +body { + background: var(--body-bg-color); + box-sizing: border-box; + color: var(--text-color); + font-family: $font-family-base; + font-size: $font-size-base; + line-height: $line-height-base; + min-height: 100%; + position: relative; + transition: padding $transition-ease; + + @if hexo-config('body_scrollbar.overlay') { + overflow-x: hidden; + @supports (overflow-x: clip) { + overflow-x: clip; + } + width: 100vw; + } + + @if hexo-config('body_scrollbar.stable') { + overflow-y: scroll; + } +} + +h1, h2, h3, h4, h5, h6 { + font-family: $font-family-headings; + font-weight: bold; + line-height: 1.5; + margin: 30px 0 15px; +} + +@for $headline from 1 through 6 { + h#{$headline} { + font-size: $font-size-headings-base - $font-size-headings-step * $headline; + } +} + +p { + margin: 0 0 20px; +} + +a { + border-bottom: 1px solid $link-decoration-color; + color: var(--link-color); + // For a:not(:any-link) + cursor: pointer; + outline: 0; + text-decoration: none; + @include word-wrap(); + + &:hover { + border-bottom-color: var(--link-hover-color); + color: var(--link-hover-color); + } +} + +iframe, img, video, embed { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 100%; +} + +hr { + background-image: repeating-linear-gradient(-45deg, $grey-lighter, $grey-lighter 4px, transparent 4px, transparent 8px); + border: 0; + height: 3px; + margin: 40px 0; +} + +blockquote { + border-left: 4px solid $grey-lighter; + color: var(--blockquote-color); + margin: 0; + padding: 0 15px; + + cite::before { + content: '-'; + padding: 0 5px; + } +} + +dt { + font-weight: bold; +} + +dd { + margin: 0; + padding: 0; +} diff --git a/assets/css/_common/scaffolding/buttons.scss b/assets/css/_common/scaffolding/buttons.scss new file mode 100644 index 0000000..a54372f --- /dev/null +++ b/assets/css/_common/scaffolding/buttons.scss @@ -0,0 +1,26 @@ +.btn { + background: var(--btn-default-bg); + border: 2px solid var(--btn-default-border-color); + border-radius: $btn-default-radius; + color: var(--btn-default-color); + display: inline-block; + font-size: $font-size-small; + line-height: 2; + padding: 0 20px; + transition: background-color $transition-ease; + + &:hover { + background: var(--btn-default-hover-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); + } + + + .btn { + margin: 0 0 8px 8px; + } + + .fa-fw { + text-align: left; + width: (18em / 14); + } +} diff --git a/assets/css/_common/scaffolding/comments.scss b/assets/css/_common/scaffolding/comments.scss new file mode 100644 index 0000000..8ace888 --- /dev/null +++ b/assets/css/_common/scaffolding/comments.scss @@ -0,0 +1,39 @@ +.comments { + margin-top: 60px; + overflow: hidden; +} + +.comment-button-group { + display: flex; + flex-wrap: wrap-reverse; + justify-content: center; + margin: 1em 0; + + .comment-button { + margin: .1em .2em; + + &.active { + background: var(--btn-default-hover-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); + } + } +} + +.comment-position { + display: none; + + &.active { + display: block; + } +} + +.tabs-comment { + margin-top: 4em; + padding-top: 0; + + .comments { + margin-top: 0; + padding-top: 0; + } +} diff --git a/assets/css/_common/scaffolding/highlight/copy-code.scss b/assets/css/_common/scaffolding/highlight/copy-code.scss new file mode 100644 index 0000000..b350a2c --- /dev/null +++ b/assets/css/_common/scaffolding/highlight/copy-code.scss @@ -0,0 +1,55 @@ +.highlight:hover .copy-btn, pre:hover .copy-btn { + opacity: 1; +} + +.copy-btn { + color: $black-dim; + cursor: pointer; + line-height: 1.6; + opacity: 0; + padding: 2px 6px; + position: absolute; + transition: opacity $transition-ease; + + @if hexo-config('codeblock.copy_button.style') == 'flat' { + background: white; + border: 0; + font-size: $font-size-smaller; + right: 0; + top: 0; + } @else if hexo-config('codeblock.copy_button.style') == 'mac' { + color: var(--highlight-foreground); + font-size: 14px; + right: 0; + top: 2px; + } @else { + background-color: $gainsboro; + background-image: linear-gradient(#fcfcfc, $gainsboro); + border: 1px solid #d5d5d5; + border-radius: 3px; + font-size: $font-size-smaller; + right: 4px; + top: 8px; + } +} + +@if hexo-config('codeblock.copy_button.style') == 'mac' { + figure.highlight { + border-radius: 5px; + box-shadow: 0 10px 30px 0 rgba(0, 0, 0, .4); + padding-top: 30px; + + .table-container { + border-radius: 0 0 5px 5px; + } + + &::before { + background: #fc625d; + box-shadow: 20px 0 #fdbc40, 40px 0 #35cd4b; + left: 12px; + margin-top: -20px; + position: absolute; + @include round-icon(12px); + } + } +} diff --git a/assets/css/_common/scaffolding/highlight/index.scss b/assets/css/_common/scaffolding/highlight/index.scss new file mode 100644 index 0000000..106e21e --- /dev/null +++ b/assets/css/_common/scaffolding/highlight/index.scss @@ -0,0 +1,140 @@ +// Use `@use` to fix issue #67 +@import '(theme.highlight.enable && theme.highlight.light.file) ? theme.highlight.light.file : null'; +@import '(theme.prism.enable && theme.prism.light) ? theme.prism.light : null'; +@import '(theme.prism.enable && theme.prism.number) ? theme.prism.number : null'; + +@media (prefers-color-scheme: dark) { + @import '(theme.darkmode && theme.highlight.enable && theme.highlight.dark.file) ? theme.highlight.dark.file : null'; + @import '(theme.darkmode && theme.prism.enable && theme.prism.dark) ? theme.prism.dark : null'; +} + +@import 'theme.codeblock.copy_button.enable ? "copy-code" : null'; + +// Placeholder: %code-inline %code-block +%code-inline { + background: var(--highlight-background); + color: var(--highlight-foreground); +} + +%code-block { + @extend %code-inline; + line-height: $line-height-code-block; + margin: 0 auto 20px; +} + +%figcaption { + background: var(--highlight-gutter-background); + color: var(--highlight-foreground); + display: flow-root; + font-size: $table-font-size; + line-height: 1.2; + padding: .5em; + + a { + color: var(--highlight-foreground); + float: right; + + &:hover { + border-bottom-color: var(--highlight-foreground); + } + } +} + +pre, code { + font-family: $code-font-family; +} + +code { + @extend %code-inline; + border-radius: 3px; + font-size: $table-font-size; + padding: 2px 4px; + @include word-wrap(); +} + +kbd { + @extend %code-inline; + border: 2px solid $grey-light; + border-radius: .2em; + box-shadow: .1em .1em .2em rgba(0, 0, 0, .1); + font-family: inherit; + padding: .1em .3em; + white-space: nowrap; +} + +// `highlight.line_number: false` and `highlight.wrap: false` +// in Hexo config generates code.highlight elements +figure.highlight { + @extend %code-block; + position: relative; + + pre { + border: 0; + margin: 0; + padding: 10px 0; + } + + table { + border: 0; + margin: 0; + width: auto; + } + + td { + border: 0; + padding: 0; + } + + figcaption { + @extend %figcaption; + } + + .gutter { + @include disable-user-select(); + + pre { + background: var(--highlight-gutter-background); + color: var(--highlight-gutter-foreground); + padding-left: 10px; + padding-right: 10px; + text-align: right; + } + } + + .code pre { + padding-left: 10px; + width: 100%; + } + + // See https://github.com/next-theme/hexo-theme-next/discussions/410 + .marked { + background: rgba(0, 0, 0, .3); + } +} + +// See https://github.com/hexojs/hexo-util/pull/229 +pre .caption, pre figcaption { + @extend %figcaption; + margin-bottom: 10px; +} + +.gist table { + width: auto; + + td { + border: 0; + } +} + +pre { + @extend %code-block; + overflow: auto; + padding: 10px; + position: relative; + + code { + background: none; + padding: 0; + text-shadow: none; + } +} diff --git a/assets/css/_common/scaffolding/index.scss b/assets/css/_common/scaffolding/index.scss new file mode 100644 index 0000000..aec7a8d --- /dev/null +++ b/assets/css/_common/scaffolding/index.scss @@ -0,0 +1,12 @@ +// +// Scaffolding +// ================================================== +@import 'normalize'; +@import 'base'; +@import 'tables'; +@import 'buttons'; +@import 'toggles'; +@import 'highlight'; +@import 'tags'; +@import 'pagination'; +@import 'comments'; diff --git a/assets/css/_common/scaffolding/normalize.scss b/assets/css/_common/scaffolding/normalize.scss new file mode 100644 index 0000000..beb43cf --- /dev/null +++ b/assets/css/_common/scaffolding/normalize.scss @@ -0,0 +1,289 @@ +/* normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +/* Document +========================================================================== */ +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections +========================================================================== */ +/** + * Remove the margin in all browsers. + */ +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: .67em 0; +} + +/* Grouping content +========================================================================== */ +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics +========================================================================== */ +/** + * Remove the gray background on active links in IE 10. + */ +a { + background: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, kbd, samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +/* Embedded content +========================================================================== */ +/** + * Remove the border on images inside links in IE 10. + */ +img { + border-style: none; +} + +/* Forms +========================================================================== */ +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ +button, input, optgroup, select, textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ +button, [type='button'], [type='reset'], [type='submit'] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, [type='button']::-moz-focus-inner, [type='reset']::-moz-focus-inner, [type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, [type='button']:-moz-focusring, [type='reset']:-moz-focusring, [type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ +fieldset { + padding: .35em .75em .625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ +[type='checkbox'], [type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type='number']::-webkit-inner-spin-button, [type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type='search'] { + outline-offset: -2px; /* 2 */ + -webkit-appearance: textfield; /* 1 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + font: inherit; /* 2 */ + -webkit-appearance: button; /* 1 */ +} + +/* Interactive +========================================================================== */ +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ +summary { + display: list-item; +} + +/* Misc +========================================================================== */ +/** + * Add the correct display in IE 10+. + */ +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ +[hidden] { + display: none; +} diff --git a/assets/css/_common/scaffolding/pagination.scss b/assets/css/_common/scaffolding/pagination.scss new file mode 100644 index 0000000..0040500 --- /dev/null +++ b/assets/css/_common/scaffolding/pagination.scss @@ -0,0 +1,55 @@ +%page-number-basic { + display: inline-block; + margin: -1px 10px 0; + padding: 0 10px; + + @include mobile() { + margin: 0 5px; + } +} + +%page-number-current { + background: $pagination-active-bg; + border-color: $pagination-active-border; + color: $pagination-active-color; +} + +.pagination { + border-top: 1px solid $pagination-border; + margin: 120px 0 0; + text-align: center; + + .prev, .next, .page-number { + @extend %page-number-basic; + border-bottom: 0; + border-top: 1px solid $pagination-link-border; + transition: border-color $transition-ease; + + &:hover { + border-top-color: $pagination-link-hover-border; + } + } + + @include mobile() { + border-top: 0; + + .prev, .next, .page-number { + border-bottom: 1px solid $pagination-link-border; + border-top: 0; + + &:hover { + border-bottom-color: $pagination-link-hover-border; + } + } + } + + .space { + @extend %page-number-basic; + margin: 0; + padding: 0; + } + + .page-number.current { + @extend %page-number-current; + } +} diff --git a/assets/css/_common/scaffolding/tables.scss b/assets/css/_common/scaffolding/tables.scss new file mode 100644 index 0000000..9f1e866 --- /dev/null +++ b/assets/css/_common/scaffolding/tables.scss @@ -0,0 +1,39 @@ +.table-container { + overflow: auto; +} + +table { + border-collapse: collapse; + border-spacing: 0; + font-size: $table-font-size; + margin: 0 0 20px; + width: 100%; +} + +tbody tr { + &:nth-of-type(odd) { + background: var(--table-row-odd-bg-color); + } + + &:hover { + background: var(--table-row-hover-bg-color); + } +} + +caption, th, td { + padding: 8px; +} + +th, td { + border: 1px solid $table-border-color; + border-bottom: 3px solid $table-cell-border-bottom-color; +} + +th { + font-weight: 700; + padding-bottom: 10px; +} + +td { + border-bottom-width: 1px; +} diff --git a/assets/css/_common/scaffolding/tags/blockquote-center.scss b/assets/css/_common/scaffolding/tags/blockquote-center.scss new file mode 100644 index 0000000..2064506 --- /dev/null +++ b/assets/css/_common/scaffolding/tags/blockquote-center.scss @@ -0,0 +1,34 @@ +// Blockquote with all children centered. +.blockquote-center { + border-left: 0; + margin: 40px 0; + padding: 0; + position: relative; + text-align: center; + + &::before, &::after { + left: 0; + line-height: 1; + opacity: .6; + position: absolute; + width: 100%; + } + + &::before { + border-top: 1px solid $grey-light; + text-align: left; + top: -20px; + @include font-family-icons('\f10d'); + } + + &::after { + border-bottom: 1px solid $grey-light; + bottom: -20px; + text-align: right; + @include font-family-icons('\f10e'); + } + + p, div { + text-align: center; + } +} diff --git a/assets/css/_common/scaffolding/tags/group-pictures.scss b/assets/css/_common/scaffolding/tags/group-pictures.scss new file mode 100644 index 0000000..3d314b1 --- /dev/null +++ b/assets/css/_common/scaffolding/tags/group-pictures.scss @@ -0,0 +1,20 @@ +.group-picture { + margin-bottom: 20px; + + .group-picture-row { + display: flex; + gap: 3px; + margin-bottom: 3px; + } + + .group-picture-column { + flex: 1; + + img { + height: 100%; + margin: 0; + object-fit: cover; + width: 100%; + } + } +} diff --git a/assets/css/_common/scaffolding/tags/index.scss b/assets/css/_common/scaffolding/tags/index.scss new file mode 100644 index 0000000..fc8eadd --- /dev/null +++ b/assets/css/_common/scaffolding/tags/index.scss @@ -0,0 +1,8 @@ +@import 'blockquote-center'; +@import 'group-pictures'; +@import 'label'; +@import 'link-grid'; +@import 'mermaid'; +@import 'note'; +@import 'pdf'; +@import 'tabs'; diff --git a/assets/css/_common/scaffolding/tags/label.scss b/assets/css/_common/scaffolding/tags/label.scss new file mode 100644 index 0000000..e4c953c --- /dev/null +++ b/assets/css/_common/scaffolding/tags/label.scss @@ -0,0 +1,12 @@ +@use 'sass:map'; + +.post-body .label { + color: $text-color; + padding: 0 2px; + + @each $type in $note-types { + &.#{$type} { + background: map.get($label, $type); + } + } +} diff --git a/assets/css/_common/scaffolding/tags/link-grid.scss b/assets/css/_common/scaffolding/tags/link-grid.scss new file mode 100644 index 0000000..20a1d58 --- /dev/null +++ b/assets/css/_common/scaffolding/tags/link-grid.scss @@ -0,0 +1,113 @@ +.post-body .link-grid { + display: grid; + // https://caniuse.com/mdn-css_properties_gap_grid_context + grid-gap: 1.5rem; + gap: 1.5rem; + grid-template-columns: 1fr 1fr; + margin-bottom: 20px; + padding: 1rem; + + @include mobile() { + grid-template-columns: 1fr; + } + + .link-grid-container { + border: solid $grey-lighter; + box-shadow: 1rem 1rem .5rem rgba(0, 0, 0, .5); + min-height: 5rem; + // Fix issue #30 + min-width: 0; + padding: .5rem; + position: relative; + transition: background .3s; + + &:hover { + animation: next-shake .5s; + background: var(--card-bg-color); + } + + &:active { + box-shadow: .5rem .5rem .25rem rgba(0, 0, 0, .5); + transform: translate(.2rem, .2rem); + } + + .link-grid-image { + border: 1px solid $grey-lighter; + border-radius: 50%; + box-sizing: border-box; + height: 5rem; + padding: 3px; + position: absolute; + width: 5rem; + } + + p { + margin: 0 1rem 0 6rem; + + &:first-of-type { + font-size: 1.2em; + } + + &:last-of-type { + font-size: .8em; + line-height: 1.3rem; + opacity: .7; + } + } + + a { + border: 0; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + } +} + +@keyframes next-shake { + 0% { + transform: translate(1pt, 1pt) rotate(0deg); + } + + 10% { + transform: translate(-1pt, -2pt) rotate(-1deg); + } + + 20% { + transform: translate(-3pt, 0pt) rotate(1deg); + } + + 30% { + transform: translate(3pt, 2pt) rotate(0deg); + } + + 40% { + transform: translate(1pt, -1pt) rotate(1deg); + } + + 50% { + transform: translate(-1pt, 2pt) rotate(-1deg); + } + + 60% { + transform: translate(-3pt, 1pt) rotate(0deg); + } + + 70% { + transform: translate(3pt, 1pt) rotate(-1deg); + } + + 80% { + transform: translate(-1pt, -1pt) rotate(1deg); + } + + 90% { + transform: translate(1pt, 2pt) rotate(0deg); + } + + 100% { + transform: translate(1pt, -2pt) rotate(-1deg); + } +} diff --git a/assets/css/_common/scaffolding/tags/mermaid.scss b/assets/css/_common/scaffolding/tags/mermaid.scss new file mode 100644 index 0000000..22ff864 --- /dev/null +++ b/assets/css/_common/scaffolding/tags/mermaid.scss @@ -0,0 +1,6 @@ +@if hexo-config('mermaid.enable') { + .mermaid { + margin-bottom: 20px; + text-align: center; + } +} diff --git a/assets/css/_common/scaffolding/tags/note.scss b/assets/css/_common/scaffolding/tags/note.scss new file mode 100644 index 0000000..d95d39a --- /dev/null +++ b/assets/css/_common/scaffolding/tags/note.scss @@ -0,0 +1,114 @@ +@use 'sass:map'; + +@if hexo-config('note.style') != 'disabled' { + .post-body .note { + $note-icons : hexo-config('note.icons'); + $note-style : hexo-config('note.style'); + + border-radius: $note-border-radius; + margin-bottom: 20px; + padding: 1em; + position: relative; + + @if $note-style == 'simple' { + border: 1px solid $gainsboro; + border-left-width: 5px; + } + + @if $note-style == 'modern' { + background: $whitesmoke; + border: 1px solid transparent; + } + + @if $note-style == 'flat' { + background: lighten($gainsboro, 65%); + border: initial; + border-left: 3px solid $gainsboro; + } + + summary { + cursor: pointer; + outline: 0; + + p { + display: inline; + } + } + + h2, h3, h4, h5, h6 { + border-bottom: initial; + margin: 0; + padding-top: 0; + } + + p, ul, ol, table, pre, blockquote, img { + &:first-child { + margin-top: 0; + } + + &:last-child { + margin-bottom: 0; + } + } + + @if $note-icons { + &:not(.no-icon) { + padding-left: 2.5em; + + &::before { + font-size: 1.5em; + left: .3em; + position: absolute; + top: calc(50% - 1em); + } + } + } + + @each $type in $note-types { + &.#{$type} { + @if $note-style == 'flat' { + background: map.get($note-bg, $type); + @if hexo-config('darkmode') { + @media (prefers-color-scheme: dark) { + background: mix(map.get($note-bg, $type), $body-bg-color-dark, 10%); + } + } + } + + @if $note-style == 'modern' { + background: map.get($note-modern-bg, $type); + border-color: map.get($note-modern-border, $type); + color: map.get($note-modern-text, $type); + + a:not(.btn) { + border-bottom-color: map.get($note-modern-text, $type); + color: map.get($note-modern-text, $type); + + &:hover { + border-bottom-color: map.get($note-modern-hover, $type); + color: map.get($note-modern-hover, $type); + } + } + } + + @if $note-style != 'modern' { + border-left-color: map.get($note-border, $type); + + h2, h3, h4, h5, h6 { + color: map.get($note-text, $type); + } + } + + @if $note-icons { + &:not(.no-icon)::before { + @include font-family-icons(map.get($note-icon, $type)); + + @if $note-style != 'modern' { + color: map.get($note-text, $type); + } + } + } + } + } + } +} diff --git a/assets/css/_common/scaffolding/tags/pdf.scss b/assets/css/_common/scaffolding/tags/pdf.scss new file mode 100644 index 0000000..a08d9cb --- /dev/null +++ b/assets/css/_common/scaffolding/tags/pdf.scss @@ -0,0 +1,8 @@ +@if hexo-config('pdf.enable') { + .pdfobject-container { + iframe, embed { + height: convert(hexo-config('pdf.height')); + width: 100%; + } + } +} diff --git a/assets/css/_common/scaffolding/tags/tabs.scss b/assets/css/_common/scaffolding/tags/tabs.scss new file mode 100644 index 0000000..5ce758c --- /dev/null +++ b/assets/css/_common/scaffolding/tags/tabs.scss @@ -0,0 +1,103 @@ +.post-body .tabs { + margin-bottom: 20px; +} + +.post-body .tabs, .tabs-comment { + padding-top: 10px; + + ul.nav-tabs { + background: if(($scheme == 'Muse') or ($scheme == 'Mist'), var(--body-bg-color), var(--content-bg-color)); + display: flex; + flex-wrap: wrap; + margin: 0; + padding: 0; + position: -webkit-sticky; + position: sticky; + top: 0; + // Fix issue #398 + z-index: $zindex-0; + + @include mobile-smallest() { + display: block; + margin-bottom: 5px; + } + + li.tab { + border-bottom: 1px solid $grey-lighter; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-radius: $tbr $tbr 0 0; + border-top: 3px solid transparent; + flex-grow: 1; + list-style-type: none; + + @include mobile-smallest() { + border-bottom: 1px solid transparent; + border-left: 3px solid transparent; + border-right: 1px solid transparent; + border-top: 1px solid transparent; + } + + @include mobile-smallest() { + border-radius: $tbr; + } + + @if hexo-config('tabs.transition.tabs') { + transition: all $transition-ease-out; + } + + a { + border-bottom: initial; + display: block; + line-height: 1.8; + padding: .25em .75em; + text-align: center; + + i { + width: (18em / 14); + } + + @if hexo-config('tabs.transition.labels') { + transition: all $transition-ease-out; + } + } + + &.active { + border-bottom-color: transparent; + border-left-color: $table-border-color; + border-right-color: $table-border-color; + border-top-color: $orange; + + @include mobile-smallest() { + border-bottom-color: $table-border-color; + border-left-color: $orange; + border-right-color: $table-border-color; + border-top-color: $table-border-color; + } + + a { + cursor: default; + } + } + } + } + + .tab-content { + border: 1px solid $table-border-color; + border-radius: 0 0 $tbr $tbr; + border-top-color: transparent; + + @include mobile-smallest() { + border-radius: $tbr; + border-top-color: $table-border-color; + } + + .tab-pane { + padding: 20px 20px 0; + + &:not(.active) { + display: none; + } + } + } +} diff --git a/assets/css/_common/scaffolding/toggles.scss b/assets/css/_common/scaffolding/toggles.scss new file mode 100644 index 0000000..54cd930 --- /dev/null +++ b/assets/css/_common/scaffolding/toggles.scss @@ -0,0 +1,26 @@ +.toggle { + line-height: 0; + + .toggle-line { + background: white; + display: block; + height: 2px; + left: 0; + position: relative; + top: 0; + transition: all .4s; + width: 100%; + + &:not(:first-child) { + margin-top: 3px; + } + } +} + +.toggle.toggle-arrow { + @include toggle-arrow(hexo-config('sidebar.position')); +} + +.toggle.toggle-close { + @include toggle-close(hexo-config('sidebar.position')); +} diff --git a/assets/css/_mixins.scss b/assets/css/_mixins.scss new file mode 100644 index 0000000..59cdf9c --- /dev/null +++ b/assets/css/_mixins.scss @@ -0,0 +1,243 @@ +@mixin mobile-smallest() { + @media (max-width: 413px) { + @content;; + } +} + +@mixin mobile-small() { + @media (max-width: 567px) { + @content; + } +} + +@mixin mobile() { + @media (max-width: 767px) { + @content; + } +} + +@mixin tablet-mobile() { + @media (max-width: 991px) { + @content; + } +} + +@mixin tablet-desktop() { + @media (min-width: 768px) { + @content; + } +} + +@mixin tablet() { + @media (min-width: 768px) and (max-width: 991px) { + @content; + } +} + +@mixin desktop() { + @media (min-width: 992px) { + @content; + } +} + +@mixin desktop-large() { + @media (min-width: 1200px) { + @content; + } +} + +@mixin desktop-largest() { + @media (min-width: 1600px) { + @content; + } +} + +@mixin word-wrap() { + overflow-wrap: break-word; +} + +@mixin disable-user-select() { + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +@mixin sidebar-inline-links-item() { + margin: 5px 0 0; + + a { + box-sizing: border-box; + display: inline-block; + max-width: 100%; + overflow: hidden; + padding: 0 5px; + text-overflow: ellipsis; + white-space: nowrap; + } +} + +@mixin flex-wrap() { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +@mixin flex-column() { + display: flex; + flex-direction: column; + justify-content: center; +} + +@mixin post-card() { + background: var(--card-bg-color); + border-left: 3px solid $red; + margin: $post-card-margin; +} + +@mixin font-family-icons($icon : '') { + @if $icon { + content: $icon; + } + font-family: 'Font Awesome 5 Free'; + font-weight: 900; +} + +@mixin main-container() { + margin: 0 auto; + width: $content-desktop; + + @include desktop-large() { + width: $content-desktop-large; + } + + @include desktop-largest() { + width: $content-desktop-largest; + } +} + +@function sidebar-toggle-alignment($reverse) { + $condition : hexo-config('sidebar.position') == 'right'; + @if ($scheme == 'Muse') or ($scheme == 'Mist') { + $condition : $condition == $reverse; + } + @return if($condition, ('left' 'right'), ('right' 'left')); +} + +@mixin sidebar-toggle-position($reverse) { + $alignment : list.nth(sidebar-toggle-alignment($reverse), 0); + #{$alignment}: $b2t-position-right; + @include tablet-mobile() { + #{$alignment}: $b2t-position-right-mobile; + } +} + +@mixin sidebar-toggle() { + background: $b2t-bg-color; + cursor: pointer; + opacity: $b2t-opacity; + position: fixed; + z-index: $zindex-3; + @include sidebar-toggle-position(false); + + &:hover { + opacity: $b2t-opacity-hover; + } + + @include tablet-mobile() { + opacity: $b2t-opacity-hover; + } +} + +@mixin round-icon($diameter) { + border-radius: 50%; + content: ' '; + height: $diameter; + width: $diameter; +} + +@mixin toggle-arrow($position) { + @if $position == 'right' { + .toggle-line:first-child { + top: 2px; + transform: rotate(-45deg); + width: 50%; + } + + .toggle-line:last-child { + top: -2px; + transform: rotate(45deg); + width: 50%; + } + } @else { + .toggle-line:first-child { + left: 50%; + top: 2px; + transform: rotate(45deg); + width: 50%; + } + + .toggle-line:last-child { + left: 50%; + top: -2px; + transform: rotate(-45deg); + width: 50%; + } + } +} + +@mixin toggle-close($position) { + .toggle-line:nth-child(2) { + opacity: 0; + } + + @if $position == 'right' { + .toggle-line:first-child { + top: 5px; + transform: rotate(-45deg); + } + + .toggle-line:last-child { + top: -5px; + transform: rotate(45deg); + } + } @else { + .toggle-line:first-child { + top: 5px; + transform: rotate(45deg); + } + + .toggle-line:last-child { + top: -5px; + transform: rotate(-45deg); + } + } +} + +@mixin site-nav-hide-by-default() { + --scroll-height: 0; + height: 0; + overflow: hidden; + transition: height $transition-ease; + + body:not(.site-nav-on) & .animated { + animation: none; + } + + body.site-nav-on & { + height: var(--scroll-height); + } +} + +@mixin button($color) { + background: transparent; + color: $color; + cursor: pointer; + line-height: 2; + padding: 0 15px; + + &:hover { + background: $color; + color: white; + } +} diff --git a/assets/css/_schemes/Gemini/index.scss b/assets/css/_schemes/Gemini/index.scss new file mode 100644 index 0000000..2846599 --- /dev/null +++ b/assets/css/_schemes/Gemini/index.scss @@ -0,0 +1,130 @@ +@import '../Pisces/_layout'; +@import '../Pisces/_header'; +@import '../Pisces/_menu'; +@import '../Pisces/_sub-menu'; +@import '../Pisces/_sidebar'; + +// ================================================== +// Rewrite _layout.styl +// ================================================== +// Sidebar padding used as main desktop content padding for sidebar padding and post blocks padding too. + +// In `source/css/_variables/Pisces.styl` there are variable for main offset: +// $sidebar-offset : 12px; +// This value alse can be changed in main NexT config as `sidebar: offset: 12` option. + +// In `source/css/_variables/base.styl` there are variables for other resolutions: +// $content-tablet-padding : 10px; +// $content-mobile-padding : 8px; +// P.S. If u want to change this paddings u may set this variables into `custom_file_path.variable` (in theme _config.yml). + +// So, it will 12px in Desktop, 10px in Tablets and 8px in Mobiles for all possible paddings. + +// ================================================== +// Desktop layout styles. +// ================================================== +// Post blocks. +.main-inner > { + .sub-menu, .post-block, .tabs-comment, .comments, .pagination { + background: var(--content-bg-color); + border-radius: $border-radius-inner; + box-shadow: $box-shadow-inner; + + &:not(:first-child):not(.sub-menu) { + border-radius: $border-radius; + box-shadow: $box-shadow; + margin-top: $sidebar-offset; + + @include tablet() { + margin-top: $content-tablet-padding; + } + + @include mobile() { + margin-top: $content-mobile-padding; + } + } + } +} + +// Post & Comments blocks. +.post-block, .comments { + padding: $content-desktop-padding; +} + +// Post delimiters. +.post-eof { + display: none; +} + +// Pagination. +.pagination { + border-top: initial; + padding: 10px 0; +} + +// ================================================== +// Headers. +// ================================================== +.post-body { + h1, h2 { + border-bottom: 1px solid $body-bg-color; + } + + h3 { + border-bottom: 1px dotted $body-bg-color; + } +} + +// ================================================== +// > 768px & < 991px +// ================================================== +@include tablet() { + // Posts in blocks. + .main-inner { + padding: $content-tablet-padding; + } + + .posts-expand { + // Components inside Posts. + .post-button { + margin-top: ($content-tablet-padding * 2); + } + } + + .post-block { + // Inside posts blocks content padding (default 40px). + padding: ($content-tablet-padding * 2); + } + + .comments { + padding: $content-tablet-padding ($content-tablet-padding * 2); + // padding: initial; + // padding-top: $content-tablet-padding; + } +} + +// ================================================== +// < 767px +// ================================================== +@include mobile() { + // Posts in blocks. + .main-inner { + padding: $content-mobile-padding; + } + + .posts-expand { + // Components inside Posts. + .post-button { + margin: $sidebar-offset 0; + } + } + + .post-block { + // Inside posts blocks content padding (default 40px). + padding: $sidebar-offset; + } + + .comments { + padding: 10px $sidebar-offset; + } +} diff --git a/assets/css/_schemes/Mist/_header.scss b/assets/css/_schemes/Mist/_header.scss new file mode 100644 index 0000000..b51c36a --- /dev/null +++ b/assets/css/_schemes/Mist/_header.scss @@ -0,0 +1,56 @@ +// Header +// -------------------------------------------------- +.header-inner { + align-items: center; + display: flex; + padding: 20px 0; + + @include mobile() { + display: block; + padding: 10px 0; + } +} + +.site-meta { + line-height: normal; + + .brand { + padding: 2px 1px; + + @include mobile() { + display: block; + } + } + + .site-title { + font-weight: bolder; + } +} + +.logo-line { + background: var(--brand-color); + display: block; + height: 2px; + margin: 0 auto; + width: 75%; + + @include mobile() { + display: none; + } +} + +.use-motion { + .logo-line:first-of-type { + transform: scaleX(0); + transform-origin: left; + } + + .logo-line:last-of-type { + transform: scaleX(0); + transform-origin: right; + } +} + +.site-subtitle { + display: none; +} diff --git a/assets/css/_schemes/Mist/_layout.scss b/assets/css/_schemes/Mist/_layout.scss new file mode 100644 index 0000000..649389c --- /dev/null +++ b/assets/css/_schemes/Mist/_layout.scss @@ -0,0 +1,43 @@ +// Tags +// -------------------------------------------------- +hr { + height: 2px; + margin: 20px 0; +} + +// Components +// -------------------------------------------------- +.btn { + padding: 0 10px; +} + +.headband { + display: none; +} + +// Pagination +// -------------------------------------------------- +.pagination { + text-align: left; + + @include mobile() { + margin: 80px 0 0; + text-align: center; + } +} + +// Footer +// -------------------------------------------------- +.footer { + background: var(--content-bg-color); + color: var(--text-color); + padding: 10px 0; +} + +.footer-inner { + text-align: left; + + @include mobile() { + text-align: center; + } +} diff --git a/assets/css/_schemes/Mist/_menu.scss b/assets/css/_schemes/Mist/_menu.scss new file mode 100644 index 0000000..6f4ae85 --- /dev/null +++ b/assets/css/_schemes/Mist/_menu.scss @@ -0,0 +1,45 @@ +// Menu +// -------------------------------------------------- +.site-nav { + flex-grow: 1; + + @include mobile() { + padding: 0 10px 0; + } +} + +.main-menu { + @include mobile() { + padding-top: 10px; + } +} + +.menu { + padding: 0; + + .menu-item { + margin: 0; + + @include mobile() { + margin-top: 5px; + } + + a { + border-radius: 2px; + padding: 0 10px; + transition-property: background; + + @include mobile() { + text-align: left; + } + } + + .badge { + background: white; + border-radius: 10px; + color: $black-light; + padding: 1px 4px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .1); + } + } +} diff --git a/assets/css/_schemes/Mist/_posts-expand.scss b/assets/css/_schemes/Mist/_posts-expand.scss new file mode 100644 index 0000000..14a1940 --- /dev/null +++ b/assets/css/_schemes/Mist/_posts-expand.scss @@ -0,0 +1,72 @@ +// Post Expand +// -------------------------------------------------- +.posts-expand { + &.index { + .post-header { + text-align: left; + + @include mobile() { + text-align: center; + } + } + + .post-meta-container { + margin-top: 5px; + } + + .post-meta { + justify-content: flex-start; + + @include mobile() { + justify-content: center; + } + } + } + + .post-eof { + display: none; + } + + .post-block:not(:first-of-type) { + margin-top: 120px; + } + + .post-header { + margin-bottom: 20px; + } + + .post-tags { + text-align: left; + + a { + background: var(--content-bg-color); + border-bottom: 0; + padding: 1px 5px; + + &:hover { + background: var(--menu-item-bg-color); + } + } + } + + .post-nav { + margin-top: 40px; + } +} + +.post-button { + margin-top: 20px; + text-align: left; + + .btn { + background: none; + border: 0; + border-bottom: 2px solid var(--btn-default-border-color); + padding: 0; + transition-property: border; + + &:hover { + border-bottom-color: var(--btn-default-hover-border-color); + } + } +} diff --git a/assets/css/_schemes/Mist/index.scss b/assets/css/_schemes/Mist/index.scss new file mode 100644 index 0000000..6969d77 --- /dev/null +++ b/assets/css/_schemes/Mist/index.scss @@ -0,0 +1,10 @@ +// +// Mist scheme +// ================================================== +@import '_layout'; +@import '_header'; +@import '_menu'; +@import '_posts-expand'; +@import '../Muse/_layout'; +@import '../Muse/_sidebar'; +@import '../Muse/_sub-menu'; diff --git a/assets/css/_schemes/Muse/_header.scss b/assets/css/_schemes/Muse/_header.scss new file mode 100644 index 0000000..d143a4b --- /dev/null +++ b/assets/css/_schemes/Muse/_header.scss @@ -0,0 +1,18 @@ +.custom-logo-image { + background: white; + margin: 0 auto 10px; + max-width: 150px; + padding: 5px; +} + +.brand { + background: var(--btn-default-bg); +} + +.header-inner { + padding-top: 100px; + + @include mobile() { + padding-top: 50px; + } +} diff --git a/assets/css/_schemes/Muse/_layout.scss b/assets/css/_schemes/Muse/_layout.scss new file mode 100644 index 0000000..e8380a7 --- /dev/null +++ b/assets/css/_schemes/Muse/_layout.scss @@ -0,0 +1,28 @@ +.main-inner { + @include main-container(); + + @include mobile() { + padding-left: 20px; + padding-right: 20px; + } +} + +.header-inner, .main-inner, .footer-inner { + @include mobile() { + width: auto; + } +} + +// Page - Container +// -------------------------------------------------- +.main-inner { + padding-bottom: $content-padding-bottom; +} + +.post-block:first-of-type { + padding-top: $posts-first-padding; + + @include mobile() { + padding-top: $posts-first-padding-mobile; + } +} diff --git a/assets/css/_schemes/Muse/_menu.scss b/assets/css/_schemes/Muse/_menu.scss new file mode 100644 index 0000000..3cc88ac --- /dev/null +++ b/assets/css/_schemes/Muse/_menu.scss @@ -0,0 +1,56 @@ +.site-nav { + @include mobile() { + padding-top: 30px; + } +} + +.main-menu { + @include mobile() { + border-bottom: 1px solid $grey-lighter; + border-top: 1px solid $grey-lighter; + } +} + +.menu { + @include mobile() { + text-align: left; + } +} + +.menu .menu-item { + @include mobile() { + margin: 0 10px; + } + + a { + border-bottom: 1px solid transparent; + + @include mobile() { + padding: 5px 10px; + } + + &:hover, &.menu-item-active { + background: transparent; + border-bottom: 1px solid var(--link-hover-color); + + @include mobile() { + border-bottom: 1px dotted $grey-lighter; + } + } + } + + .fa, .fab, .far, .fas { + @include tablet-desktop() { + display: block; + line-height: 2; + margin-right: 0; + width: 100%; + } + } + + .badge { + background: $gainsboro; + color: $black-light; + padding: 1px 4px; + } +} diff --git a/assets/css/_schemes/Muse/_sidebar.scss b/assets/css/_schemes/Muse/_sidebar.scss new file mode 100644 index 0000000..d1651f5 --- /dev/null +++ b/assets/css/_schemes/Muse/_sidebar.scss @@ -0,0 +1,94 @@ +@if hexo-config('sidebar.position') == 'right' { + .sidebar-active { + @include desktop() { + padding-right: $sidebar-desktop; + } + } + + .sidebar { + right: 0 - $sidebar-desktop; + + .sidebar-active & { + right: 0; + } + } +} @else { + .sidebar-active { + @include desktop() { + padding-left: $sidebar-desktop; + } + } + + .sidebar { + left: 0 - $sidebar-desktop; + + .sidebar-active & { + left: 0; + } + } +} + +.sidebar { + background: $black-deep; + bottom: 0; + @if not hexo-config('back2top.sidebar') { + box-shadow: inset 0 2px 6px black; + } + position: fixed; + top: 0; + transition: all $transition-ease-out; + width: $sidebar-desktop; + z-index: $zindex-2; + + a { + border-bottom-color: $black-light; + color: $grey-dark; + + &:hover { + border-bottom-color: $gainsboro; + color: $gainsboro; + } + } +} + +.links-of-author { + &:not(:first-child) { + margin-top: 15px; + } + + a { + border-bottom-color: $black-light; + display: inline-block; + margin-bottom: 10px; + margin-right: 10px; + vertical-align: middle; + + @if hexo-config('social_icons.transition') { + transition: all $transition-ease; + } + + &::before { + background: rgb(random(255), random(255), random(255)); + display: inline-block; + margin-right: 3px; + transform: translateY(-2px); + @include round-icon(4px); + } + } +} + +.links-of-blogroll-item { + @if hexo-config('links_settings.layout') == 'inline' { + display: inline-block; + } + padding: 2px 10px; + + a { + box-sizing: border-box; + display: inline-block; + max-width: 280px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +} diff --git a/assets/css/_schemes/Muse/_sub-menu.scss b/assets/css/_schemes/Muse/_sub-menu.scss new file mode 100644 index 0000000..59bf193 --- /dev/null +++ b/assets/css/_schemes/Muse/_sub-menu.scss @@ -0,0 +1,7 @@ +.sub-menu { + margin: 10px 0; + + .menu-item { + display: inline-block; + } +} diff --git a/assets/css/_schemes/Muse/index.scss b/assets/css/_schemes/Muse/index.scss new file mode 100644 index 0000000..959b7ae --- /dev/null +++ b/assets/css/_schemes/Muse/index.scss @@ -0,0 +1,5 @@ +@import '_layout'; +@import '_header'; +@import '_menu'; +@import '_sub-menu'; +@import '_sidebar'; diff --git a/assets/css/_schemes/Pisces/_header.scss b/assets/css/_schemes/Pisces/_header.scss new file mode 100644 index 0000000..82fabe7 --- /dev/null +++ b/assets/css/_schemes/Pisces/_header.scss @@ -0,0 +1,35 @@ +.site-brand-container { + background: var(--theme-color); + + .site-nav-on & { + @include tablet-mobile() { + box-shadow: 0 0 16px rgba(0, 0, 0, .5); + } + } +} + +.site-meta { + padding: 20px 0; +} + +.brand { + padding: 0; +} + +.site-subtitle { + margin: 10px 10px 0; +} + +.site-nav-toggle, .site-nav-right { + @include tablet() { + @include flex-column(); + } + + .toggle { + color: white; + + .toggle-line { + background: white; + } + } +} diff --git a/assets/css/_schemes/Pisces/_layout.scss b/assets/css/_schemes/Pisces/_layout.scss new file mode 100644 index 0000000..aa4a732 --- /dev/null +++ b/assets/css/_schemes/Pisces/_layout.scss @@ -0,0 +1,54 @@ +.header-inner { + background: var(--content-bg-color); + border-radius: $border-radius-inner; + box-shadow: $box-shadow-inner; + width: $sidebar-desktop; + + @include tablet-mobile() { + border-radius: initial; + width: auto; + } +} + +.main { + // Make sure that .header and .main-inner are the same height + // Required for .sidebar `position: sticky;` + align-items: stretch; + display: flex; + justify-content: space-between; + @include main-container(); + + @if hexo-config('sidebar.position') == 'right' { + flex-direction: row-reverse; + } + + @include tablet-mobile() { + display: block; + width: auto; + } +} + +.main-inner { + border-radius: $border-radius-inner; + box-sizing: border-box; + width: $content-wrap; + + @include tablet-mobile() { + border-radius: initial; + width: 100%; + } +} + +.footer-inner { + @if hexo-config('sidebar.position') == 'right' { + padding-right: $sidebar-desktop + $sidebar-offset; + } @else { + padding-left: $sidebar-desktop + $sidebar-offset; + } + + @include tablet-mobile() { + padding-left: 0; + padding-right: 0; + width: auto; + } +} diff --git a/assets/css/_schemes/Pisces/_menu.scss b/assets/css/_schemes/Pisces/_menu.scss new file mode 100644 index 0000000..a3c396d --- /dev/null +++ b/assets/css/_schemes/Pisces/_menu.scss @@ -0,0 +1,46 @@ +.site-nav { + @include tablet() { + @include site-nav-hide-by-default(); + } +} + +.menu .menu-item { + display: block; + margin: 0; + + a { + padding: 5px 20px; + position: relative; + text-align: left; + transition-property: background-color; + } + + @include tablet-mobile() { + &.menu-item-search { + display: none; + } + } + + .badge { + background: $grey-light; + border-radius: 10px; + color: var(--content-bg-color); + float: right; + padding: 2px 5px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .1); + } +} + +@if not hexo-config('menu_settings.badges') { + .main-menu .menu-item-active::after { + background: $grey; + border-radius: 50%; + content: ' '; + height: 6px; + margin-top: -3px; + position: absolute; + right: 15px; + top: 50%; + width: 6px; + } +} diff --git a/assets/css/_schemes/Pisces/_sidebar.scss b/assets/css/_schemes/Pisces/_sidebar.scss new file mode 100644 index 0000000..775e9e0 --- /dev/null +++ b/assets/css/_schemes/Pisces/_sidebar.scss @@ -0,0 +1,92 @@ +.sidebar { + margin-top: $sidebar-offset; + // https://caniuse.com/css-sticky + position: -webkit-sticky; + position: sticky; + top: $sidebar-offset; + width: $sidebar-desktop; + + @include tablet-mobile() { + display: none; + } + + @if hexo-config('motion.enable') and hexo-config('motion.transition.sidebar') { + visibility: hidden; + } +} + +.sidebar-toggle { + display: none; +} + +.sidebar-inner { + background: var(--content-bg-color); + border-radius: $border-radius; + box-shadow: $box-shadow; + box-sizing: border-box; + color: var(--text-color); +} + +.site-state-item { + padding: 0 10px; +} + +.sidebar .sidebar-button { + border-bottom: 1px dotted $grey-light; + border-top: 1px dotted $grey-light; + + button { + border: 0; + color: $orange; + display: block; + width: 100%; + + &:hover { + background: none; + border: 0; + color: darken($orange, 20%); + } + } +} + +.links-of-author { + @include flex-wrap(); +} + +.links-of-author-item { + @include sidebar-inline-links-item(); + + @if not hexo-config('social_icons.icons_only') { + width: 50%; + } + + a { + border-bottom: 0; + border-radius: 4px; + display: block; + + &:hover { + background: var(--body-bg-color); + } + } +} + +.links-of-blogroll-item { + @if hexo-config('links_settings.layout') == 'inline' { + display: inline-block; + max-width: 100%; + @include sidebar-inline-links-item(); + } +} + +@if hexo-config('back2top.sidebar') { + // Only when back2top.sidebar is true, apply the following styles + .back-to-top { + background: var(--body-bg-color); + margin: 8px - $sidebar-offset -10px -18px; + + &.back-to-top-on { + margin-top: 16px; + } + } +} diff --git a/assets/css/_schemes/Pisces/_sub-menu.scss b/assets/css/_schemes/Pisces/_sub-menu.scss new file mode 100644 index 0000000..166f600 --- /dev/null +++ b/assets/css/_schemes/Pisces/_sub-menu.scss @@ -0,0 +1,28 @@ +.sub-menu { + margin: 0; + padding: 6px 0; + + .menu-item { + display: inline-block; + + a { + background: transparent; + margin: 5px 10px; + padding: initial; + + &:hover { + background: transparent; + color: $sidebar-highlight; + } + } + } + + .menu-item-active { + border-bottom-color: $sidebar-highlight; + color: $sidebar-highlight; + + &:hover { + border-bottom-color: $sidebar-highlight; + } + } +} diff --git a/assets/css/_schemes/Pisces/index.scss b/assets/css/_schemes/Pisces/index.scss new file mode 100644 index 0000000..c07d31b --- /dev/null +++ b/assets/css/_schemes/Pisces/index.scss @@ -0,0 +1,30 @@ +@import '_layout'; +@import '_header'; +@import '_menu'; +@import '_sub-menu'; +@import '_sidebar'; + +.main-inner { + background: var(--content-bg-color); + box-shadow: $box-shadow-inner; + padding: $content-desktop-padding; + + @include tablet-mobile() { + padding: 20px; + } +} + +// Sub-menu(s). +.sub-menu { + border-bottom: 1px solid $table-border-color; +} + +.post-block:first-of-type { + padding-top: 40px; +} + +.pagination { + @include mobile() { + margin-bottom: 10px; + } +} diff --git a/assets/css/_variables/Gemini.scss b/assets/css/_variables/Gemini.scss new file mode 100644 index 0000000..11e362b --- /dev/null +++ b/assets/css/_variables/Gemini.scss @@ -0,0 +1,18 @@ +// Variables of Gemini scheme +// ================================================== + +@import 'Pisces'; + +// Settings for some of the most global styles. +// -------------------------------------------------- +$body-bg-color : #eee; + +// Borders. +// -------------------------------------------------- +$box-shadow-inner : 0 2px 2px 0 rgba(0, 0, 0, .12), 0 3px 1px -2px rgba(0, 0, 0, .06), 0 1px 5px 0 rgba(0, 0, 0, .12); +$box-shadow : 0 2px 2px 0 rgba(0, 0, 0, .12), 0 3px 1px -2px rgba(0, 0, 0, .06), 0 1px 5px 0 rgba(0, 0, 0, .12), 0 -1px .5px 0 rgba(0, 0, 0, .09); + +$border-radius-inner : initial; +$border-radius : initial; +// $border-radius-inner : 0 0 3px 3px; +// $border-radius : 3px; diff --git a/assets/css/_variables/Mist.scss b/assets/css/_variables/Mist.scss new file mode 100644 index 0000000..9049411 --- /dev/null +++ b/assets/css/_variables/Mist.scss @@ -0,0 +1,25 @@ +// Variables of Mist scheme +// ================================================== + +@import 'Muse'; + +$content-padding-bottom : 80px; +$posts-first-padding : 80px; +$posts-first-padding-mobile : 60px; + +$link-decoration-color : $grey-light; +$content-bg-color : $whitesmoke; +$menu-item-bg-color : $grey-lighter; + +$head-bg : var(--content-bg-color); +$brand-color : $black-deep; +$brand-hover-color : $brand-color; + +$posts-collapse-left : 0; + +$btn-default-bg : transparent; +$btn-default-color : var(--link-color); +$btn-default-hover-bg : transparent; +$btn-default-border-color : var(--link-color); +$btn-default-hover-color : var(--link-hover-color); +$btn-default-hover-border-color : var(--link-hover-color); diff --git a/assets/css/_variables/Muse.scss b/assets/css/_variables/Muse.scss new file mode 100644 index 0000000..e5d17e9 --- /dev/null +++ b/assets/css/_variables/Muse.scss @@ -0,0 +1,9 @@ +// Variables of Muse scheme +// ================================================== + +$sidebar-width : if(type-of(hexo-config('sidebar.width')) == number, hexo-config('sidebar.width'), 320); +$sidebar-desktop : $sidebar-width * 1px; + +$content-padding-bottom : 60px; +$posts-first-padding : 70px; +$posts-first-padding-mobile : 35px; diff --git a/assets/css/_variables/Pisces.scss b/assets/css/_variables/Pisces.scss new file mode 100644 index 0000000..4dd3672 --- /dev/null +++ b/assets/css/_variables/Pisces.scss @@ -0,0 +1,68 @@ +// Variables of Pisces scheme +// ================================================== + +// Settings for some of the most global styles. +// -------------------------------------------------- +$body-bg-color : #f5f7f9; + +$sidebar-width : if(type-of(hexo-config('sidebar.width')) == number, hexo-config('sidebar.width'), 240); +$sidebar-desktop : $sidebar-width * 1px; +$content-wrap : calc(100% - #{$sidebar-width + $sidebar-offset}); + +$content-desktop : calc(100% - #{$content-desktop-padding / 2}); +$content-desktop-large : 1160px; +$content-desktop-largest : 73%; + + +// Borders +// -------------------------------------------------- +$box-shadow-inner : initial; +$box-shadow : initial; + +$border-radius-inner : initial; +$border-radius : initial; + + +// Header +// -------------------------------------------------- +$subtitle-color : $grey-lighter; + +// Sidebar +// -------------------------------------------------- +$sidebar-nav-color : var(--text-color); +$sidebar-nav-hover-color : $orange; +$sidebar-highlight : $orange; + +$site-author-image-width : 120px; +$site-author-image-border-width : 1px; +$site-author-image-border-color : $gainsboro; + +$site-author-name-margin : 0; +$site-author-name-color : var(--text-color); +$site-author-name-weight : 600; + +$site-description-font-size : $font-size-smaller; +$site-description-color : $grey-dark; +$site-description-margin-top : 0; + +$site-state-item-count-font-size : $font-size-medium; +$site-state-item-name-font-size : $font-size-smaller; +$site-state-item-name-color : $grey-dark; + + +// Components +// -------------------------------------------------- + +// Button +$btn-default-radius : 2px; +$btn-default-bg : white; +$btn-default-color : $text-color; +$btn-default-border-color : $text-color; +$btn-default-hover-bg : $black-deep; +$btn-default-hover-color : white; + +// Back to top +$b2t-opacity : .6; +$b2t-opacity-hover : .8; +$b2t-position-bottom : -100px; +$b2t-position-bottom-on : 30px; diff --git a/assets/css/_variables/base.scss b/assets/css/_variables/base.scss new file mode 100644 index 0000000..635854a --- /dev/null +++ b/assets/css/_variables/base.scss @@ -0,0 +1,394 @@ +@use 'sass:map'; + +// +// Variables +// ================================================== + + +// Color system +// -------------------------------------------------- +$whitesmoke : #f5f5f5; +$gainsboro : #eee; +$grey-lighter : #ddd; +$grey-light : #ccc; +$grey : #bbb; +$grey-dark : #999; +$grey-dim : #666; +$black-light : #555; +$black-dim : #333; +$black-deep : #222; +$red : #ff2a2a; +$blue-bright : #87daff; +$blue : #0684bd; +$blue-deep : #262a30; +$orange : #fc6423; + + +// Transition +// -------------------------------------------------- +$transition-ease : .2s ease-in-out; +$transition-ease-in : .2s ease-in; +$transition-ease-out : .2s ease-out; + + +// Scaffolding +// Settings for some of the most global styles. +// -------------------------------------------------- +// Global text color on +$text-color : $black-light; +$text-color-dark : $grey-light; + +// Global link color. +$link-color : $black-light; +$link-color-dark : $grey-light; +$link-hover-color : $black-deep; +$link-hover-color-dark : $gainsboro; +$link-decoration-color : $grey-dark; + +$blockquote-color : $grey-dim; +$blockquote-color-dark : $grey; + +// Global border color. +$border-color : $grey-light; + +// Background color for +$body-bg-color : white; +$body-bg-color-dark : #282828; +$content-bg-color : white; +$content-bg-color-dark : $black-dim; + +// Selection +$selection-bg : $blue-deep; +$selection-color : $gainsboro; + +// Dark mode color +$card-bg-color : $whitesmoke; +$card-bg-color-dark : $black-light; + +$menu-item-bg-color : $whitesmoke; +$menu-item-bg-color-dark : $black-light; + +$theme-color = convert(hexo-config('theme_color.light')); +$theme-color-dark = convert(hexo-config('theme_color.dark')); + +// Typography +// Font, line-height, and elements colors. +// -------------------------------------------------- +@function get-font-family($config) { + $custom-family : hexo-config('font.' + $config + '.family'); + @return if(type-of($custom-family) == string, unquote($custom-family), null); +} + +// Font families. +$font-family-chinese : 'PingFang SC', 'Microsoft YaHei'; + +$font-family-base : $font-family-chinese, sans-serif; +@if get-font-family('global') { + $font-family-base : join(get-font-family('global'), $font-family-base); +} + +$font-family-logo : $font-family-base; +@if get-font-family('title') { + $font-family-logo : join(get-font-family('title'), $font-family-logo); +} + +$font-family-headings : $font-family-base; +@if get-font-family('headings') { + $font-family-headings : join(get-font-family('headings'), $font-family-headings); +} + +$font-family-posts : $font-family-base; +@if get-font-family('posts') { + $font-family-posts : join(get-font-family('posts'), $font-family-posts); +} + +$font-family-monospace : consolas, Menlo, monospace, $font-family-chinese; +@if get-font-family('codes') { + $font-family-monospace : join(get-font-family('codes'), $font-family-monospace); +} + + +// Font size +$font-size-base : if((hexo-config('font.enable') and type-of(hexo-config('font.global.size')) == number), hexo-config('font.global.size') * 1em, 1em); +$font-size-smallest : .75em; +$font-size-smaller : .8125em; +$font-size-small : .875em; +$font-size-medium : 1em; +$font-size-large : 1.125em; +$font-size-larger : 1.25em; +$font-size-largest : 1.5em; + + +// Headings font size +$font-size-headings-step : .125em; +$font-size-headings-base : if((hexo-config('font.enable') and type-of(hexo-config('font.headings.size')) == number), hexo-config('font.headings.size') * 1em, 1.625em); + + +// Global line height +$line-height-base : 2; +$line-height-code-block : 1.6; // Can't be less than 1.3; + + +// Z-index master list +// -------------------------------------------------- +// Fix issue https://github.com/next-theme/theme-next-docs/issues/54 +$zindex-0 : 5; +$zindex-1 : 10; +$zindex-2 : 20; +$zindex-3 : 30; +$zindex-4 : 40; +$zindex-5 : 50; + + +// Table +// -------------------------------------------------- +$table-border-color : $grey-lighter; +$table-font-size : $font-size-small; +$table-cell-border-bottom-color : $grey-lighter; +$table-row-odd-bg-color : #f9f9f9; +$table-row-odd-bg-color-dark : #282828; +$table-row-hover-bg-color : $whitesmoke; +$table-row-hover-bg-color-dark : #363636; + + +// Code & Code Blocks +// -------------------------------------------------- +$code-font-family : $font-family-monospace; + +$highlight-background : hexo-config('highlight.light.background'); +$highlight-foreground : hexo-config('highlight.light.foreground'); +$highlight-gutter-background : mix($highlight-background, $highlight-foreground, 90%); +$highlight-gutter-foreground : mix($highlight-background, $highlight-foreground, 10%); + +$highlight-background-dark : hexo-config('highlight.dark.background'); +$highlight-foreground-dark : hexo-config('highlight.dark.foreground'); +$highlight-gutter-background-dark : mix($highlight-background-dark, $highlight-foreground-dark, 90%); +$highlight-gutter-foreground-dark : mix($highlight-background-dark, $highlight-foreground-dark, 10%); + + +// Buttons +// -------------------------------------------------- +$btn-default-radius : 0; +$btn-default-bg : $black-deep; +$btn-default-bg-dark : $black-deep; +$btn-default-color : white; +$btn-default-color-dark : $text-color-dark; +$btn-default-border-color : $black-deep; +$btn-default-border-color-dark : $black-light; +$btn-default-hover-bg : white; +$btn-default-hover-bg-dark : $grey-dim; +$btn-default-hover-color : $black-deep; +$btn-default-hover-color-dark : $text-color-dark; +$btn-default-hover-border-color : $black-deep; +$btn-default-hover-border-color-dark : $grey-dim; + + +// Pagination +// -------------------------------------------------- +$pagination-border : $gainsboro; + +$pagination-link-bg : transparent; +$pagination-link-color : $link-color; +$pagination-link-border : $gainsboro; + +$pagination-link-hover-bg : transparent; +$pagination-link-hover-color : $link-color; +$pagination-link-hover-border : var(--link-hover-color); + +$pagination-active-bg : $grey-light; +$pagination-active-color : var(--content-bg-color); +$pagination-active-border : $grey-light; + + +// Layout sizes +// -------------------------------------------------- +$content-desktop : 700px; +$content-desktop-large : 800px; +$content-desktop-largest : 900px; + +$content-desktop-padding : 40px; +$content-tablet-padding : 10px; +$content-mobile-padding : 8px; + + +// Headband +// -------------------------------------------------- +$headband-height : 3px; +$headband-bg : var(--theme-color); + + +// Section Header +// Variables for header section elements. +// -------------------------------------------------- +$head-bg : transparent; + +// Site Meta +$brand-color : white; +$brand-hover-color : white; +$brand-color-dark : $grey-lighter; +$brand-hover-color-dark : $grey-lighter; + +$font-size-title : if((hexo-config('font.enable') and type-of(hexo-config('font.title.size')) == number), hexo-config('font.title.size') * 1em, 1.375em); +$font-size-subtitle : $font-size-smaller; +$subtitle-color : $grey-dark; +$site-subtitle-color : $grey-dark; + + +// Posts Collpase +// -------------------------------------------------- +$posts-collapse-margin : 35px; +$posts-collapse-margin-mobile : 0; + + +// Tag Cloud +// -------------------------------------------------- +$tag-cloud-start : #aaa; +$tag-cloud-end : #111; +$tag-cloud-start-dark : #555; +$tag-cloud-end-dark : #eee; + + +// Sidebar +// Variables for sidebar section elements. +// -------------------------------------------------- + +$sidebar-padding : if(type-of(hexo-config('sidebar.padding')) == number, hexo-config('sidebar.padding') * 1px, 18px); +$sidebar-offset : if(type-of(hexo-config('sidebar.offset')) == number, hexo-config('sidebar.offset') * 1px, 12px); +$sidebar-nav-color : $grey-dim; +$sidebar-nav-hover-color : $whitesmoke; +$sidebar-highlight : $blue-bright; + +$site-author-image-width : 96px; +$site-author-image-border-width : 2px; +$site-author-image-border-color : $black-dim; + +$site-author-name-margin : 5px 0 0; +$site-author-name-color : $whitesmoke; +$site-author-name-weight : normal; + +$site-description-font-size : $font-size-medium; +$site-description-color : $grey-dark; +$site-description-margin-top : 5px; + +$site-state-item-count-font-size : $font-size-larger; +$site-state-item-name-font-size : $font-size-small; +$site-state-item-name-color : inherit; + + +// Components +// -------------------------------------------------- +// Back to top +$b2t-opacity : .8; +$b2t-opacity-hover : 1; +$b2t-position-bottom : -100px; +$b2t-position-bottom-on : 19px; +$b2t-position-right : 30px; +$b2t-position-right-mobile : 20px; +$b2t-font-size : 12px; +$b2t-color : white; +$b2t-bg-color : $black-deep; + +// .post-expand .post-eof +// In Muse scheme, margin above and below the post separator +$post-eof-margin-top : 80px; // or 160px for more white space; +$post-eof-margin-bottom : 60px; // or 120px for less white space; + +$post-card-margin : 1em 0 0; + + +// Note colors +// -------------------------------------------------- +// Read note light_bg_offset from NexT config and set in '$lbg%' to use it as string variable. +$lbg : if(type-of(hexo-config('note.light_bg_offset')) == number, hexo-config('note.light_bg_offset') * 1%, 0); +$note-types : 'default' 'primary' 'info' 'success' 'warning' 'danger'; + +$note-border-radius : 3px; + +$note-border : ( + 'default' : #777, + 'primary' : #6f42c1, + 'info' : #428bca, + 'success' : #5cb85c, + 'warning' : #f0ad4e, + 'danger' : #d9534f +); + +$note-bg : ( + 'default' : lighten(adjust-hue(map.get($note-border, 'default'), 0), 94% + $lbg), + 'primary' : lighten(adjust-hue(map.get($note-border, 'primary'), 10), 92% + $lbg), + 'info' : lighten(adjust-hue(map.get($note-border, 'info'), -10), 91% + $lbg), + 'success' : lighten(adjust-hue(map.get($note-border, 'success'), 10), 90% + $lbg), + 'warning' : lighten(adjust-hue(map.get($note-border, 'warning'), 10), 88% + $lbg), + 'danger' : lighten(adjust-hue(map.get($note-border, 'danger'), -10), 92% + $lbg) +); + +$note-text : ( + 'default' : map.get($note-border, 'default'), + 'primary' : map.get($note-border, 'primary'), + 'info' : map.get($note-border, 'info'), + 'success' : map.get($note-border, 'success'), + 'warning' : map.get($note-border, 'warning'), + 'danger' : map.get($note-border, 'danger') +); + +$note-icon : ( + 'default' : '\f0a9', + 'primary' : '\f055', + 'info' : '\f05a', + 'success' : '\f058', + 'warning' : '\f06a', + 'danger' : '\f056' +); + +$note-modern-border : ( + 'default' : #e1e1e1, + 'primary' : #e1c2ff, + 'info' : #b3e5ef, + 'success' : #d0e6be, + 'warning' : #fae4cd, + 'danger' : #ebcdd2 +); + +$note-modern-bg : ( + 'default' : lighten(adjust-hue(map.get($note-modern-border, 'default'), 10), 60% + ($lbg * 4)), + 'primary' : lighten(adjust-hue(map.get($note-modern-border, 'primary'), 10), 40% + ($lbg * 4)), + 'info' : lighten(adjust-hue(map.get($note-modern-border, 'info'), 10), 50% + ($lbg * 4)), + 'success' : lighten(adjust-hue(map.get($note-modern-border, 'success'), 10), 40% + ($lbg * 4)), + 'warning' : lighten(adjust-hue(map.get($note-modern-border, 'warning'), 10), 43% + ($lbg * 4)), + 'danger' : lighten(adjust-hue(map.get($note-modern-border, 'danger'), 10), 35% + ($lbg * 4)) +); + +$note-modern-text : ( + 'default' : $grey-dim, + 'primary' : #6f42c1, + 'info' : #31708f, + 'success' : #3c763d, + 'warning' : #8a6d3b, + 'danger' : #a94442 +); + +$note-modern-hover : ( + 'default' : darken(adjust-hue(map.get($note-modern-text, 'default'), -10), 32%), + 'primary' : darken(adjust-hue(map.get($note-modern-text, 'primary'), -10), 22%), + 'info' : darken(adjust-hue(map.get($note-modern-text, 'info'), -10), 32%), + 'success' : darken(adjust-hue(map.get($note-modern-text, 'success'), -10), 27%), + 'warning' : darken(adjust-hue(map.get($note-modern-text, 'warning'), -10), 18%), + 'danger' : darken(adjust-hue(map.get($note-modern-text, 'danger'), -10), 22%) +); + + +// Tabs border radius +// -------------------------------------------------- +$tbr : 0; + + +// Label colors +// -------------------------------------------------- +$label : ( + 'default' : lighten(adjust-hue(map.get($note-border, 'default'), 0), 89% + $lbg), + 'primary' : lighten(adjust-hue(map.get($note-border, 'primary'), 10), 87% + $lbg), + 'info' : lighten(adjust-hue(map.get($note-border, 'info'), -10), 86% + $lbg), + 'success' : lighten(adjust-hue(map.get($note-border, 'success'), 10), 85% + $lbg), + 'warning' : lighten(adjust-hue(map.get($note-border, 'warning'), 10), 83% + $lbg), + 'danger' : lighten(adjust-hue(map.get($note-border, 'danger'), -10), 87% + $lbg) +); diff --git a/assets/css/main.scss b/assets/css/main.scss new file mode 100644 index 0000000..0d8e4df --- /dev/null +++ b/assets/css/main.scss @@ -0,0 +1,42 @@ +// CSS Style Guide: https://codeguide.co/#css + + +//$scheme : if(hexo-config('scheme'), hexo-config('scheme'), 'Muse'); + + +// Variables Layer +// -------------------------------------------------- +@import '_variables/base'; +@import '"_variables/" + theme.scheme'; +@import 'theme.injects.variable'; + +// Mixins Layer +// -------------------------------------------------- +@import '_mixins'; +@import 'theme.injects.mixin'; + +// Dark mode colors +// -------------------------------------------------- +@import '_colors'; + +// Common Layer +// -------------------------------------------------- + +// Scaffolding +@import '_common/scaffolding'; + +// Layout +@import '_common/outline'; + +// Components +@import '_common/components'; + + +// Schemes Layer +// -------------------------------------------------- +@import '"_schemes/" + theme.scheme'; + + +// Custom Layer +// -------------------------------------------------- +@import 'theme.injects.style'; diff --git a/assets/css/noscript.scss b/assets/css/noscript.scss new file mode 100644 index 0000000..2ca321f --- /dev/null +++ b/assets/css/noscript.scss @@ -0,0 +1,30 @@ +body { margin-top: 2rem; } + +.use-motion .menu-item, +.use-motion .sidebar, +.use-motion .post-block, +.use-motion .pagination, +.use-motion .comments, +.use-motion .post-header, +.use-motion .post-body, +.use-motion .collection-header { + visibility: visible; +} + +.use-motion header.header, +.use-motion .site-brand-container .toggle, +.use-motion .footer { opacity: initial; } + +.use-motion .site-title, +.use-motion .site-subtitle, +.use-motion .custom-logo-image { + opacity: initial; + top: initial; +} + +.use-motion .logo-line { + transform: scaleX(1); +} + +.search-pop-overlay, .sidebar-nav { display: none; } +.sidebar-panel { display: block; } diff --git a/assets/js/bookmark.js b/assets/js/bookmark.js new file mode 100644 index 0000000..8e3ae6a --- /dev/null +++ b/assets/js/bookmark.js @@ -0,0 +1,56 @@ +/* global CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + 'use strict'; + + const doSaveScroll = () => { + localStorage.setItem('bookmark' + location.pathname, window.scrollY); + }; + + const scrollToMark = () => { + let top = localStorage.getItem('bookmark' + location.pathname); + top = parseInt(top, 10); + // If the page opens with a specific hash, just jump out + if (!isNaN(top) && location.hash === '') { + // Auto scroll to the position + window.anime({ + targets : document.scrollingElement, + duration : 200, + easing : 'linear', + scrollTop: top + }); + } + }; + // Register everything + const init = function(trigger) { + // Create a link element + const link = document.querySelector('.book-mark-link'); + // Scroll event + window.addEventListener('scroll', () => link.classList.toggle('book-mark-link-fixed', window.scrollY === 0), { passive: true }); + // Register beforeunload event when the trigger is auto + if (trigger === 'auto') { + // Register beforeunload event + window.addEventListener('beforeunload', doSaveScroll); + document.addEventListener('pjax:send', doSaveScroll); + } + // Save the position by clicking the icon + link.addEventListener('click', () => { + doSaveScroll(); + window.anime({ + targets : link, + duration: 200, + easing : 'linear', + top : -30, + complete: () => { + setTimeout(() => { + link.style.top = ''; + }, 400); + } + }); + }); + scrollToMark(); + document.addEventListener('pjax:success', scrollToMark); + }; + + init(CONFIG.bookmark.save); +}); diff --git a/assets/js/comments-buttons.js b/assets/js/comments-buttons.js new file mode 100644 index 0000000..505c21b --- /dev/null +++ b/assets/js/comments-buttons.js @@ -0,0 +1,25 @@ +/* global CONFIG */ + +(function() { + const commentButton = document.querySelectorAll('.comment-button'); + commentButton.forEach(element => { + const commentClass = element.classList[2]; + element.addEventListener('click', () => { + commentButton.forEach(active => active.classList.toggle('active', active === element)); + document.querySelectorAll('.comment-position').forEach(active => active.classList.toggle('active', active.classList.contains(commentClass))); + if (CONFIG.comments.storage) { + localStorage.setItem('comments_active', commentClass); + } + }); + }); + let { activeClass } = CONFIG.comments; + if (CONFIG.comments.storage) { + activeClass = localStorage.getItem('comments_active') || activeClass; + } + if (activeClass) { + const activeButton = document.querySelector(`.comment-button.${activeClass}`); + if (activeButton) { + activeButton.click(); + } + } +})(); diff --git a/assets/js/comments.js b/assets/js/comments.js new file mode 100644 index 0000000..4045e8c --- /dev/null +++ b/assets/js/comments.js @@ -0,0 +1,21 @@ +/* global CONFIG */ + +window.addEventListener('tabs:register', () => { + let { activeClass } = CONFIG.comments; + if (CONFIG.comments.storage) { + activeClass = localStorage.getItem('comments_active') || activeClass; + } + if (activeClass) { + const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`); + if (activeTab) { + activeTab.click(); + } + } +}); +if (CONFIG.comments.storage) { + window.addEventListener('tabs:click', event => { + if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return; + const commentClass = event.target.classList[1]; + localStorage.setItem('comments_active', commentClass); + }); +} diff --git a/assets/js/config.js b/assets/js/config.js new file mode 100644 index 0000000..caa0075 --- /dev/null +++ b/assets/js/config.js @@ -0,0 +1,66 @@ +if (!window.NexT) window.NexT = {}; + +(function() { + const className = 'next-config'; + + const staticConfig = {}; + let variableConfig = {}; + + const parse = text => JSON.parse(text || '{}'); + + const update = name => { + const targetEle = document.querySelector(`.${className}[data-name="${name}"]`); + if (!targetEle) return; + const parsedConfig = parse(targetEle.text); + if (name === 'main') { + Object.assign(staticConfig, parsedConfig); + } else { + variableConfig[name] = parsedConfig; + } + }; + + update('main'); + + window.CONFIG = new Proxy({}, { + get(overrideConfig, name) { + let existing; + if (name in staticConfig) { + existing = staticConfig[name]; + } else { + if (!(name in variableConfig)) update(name); + existing = variableConfig[name]; + } + + // For unset override and mixable existing + if (!(name in overrideConfig) && typeof existing === 'object') { + // Get ready to mix. + overrideConfig[name] = {}; + } + + if (name in overrideConfig) { + const override = overrideConfig[name]; + + // When mixable + if (typeof override === 'object' && typeof existing === 'object') { + // Mix, proxy changes to the override. + return new Proxy({ ...existing, ...override }, { + set(target, prop, value) { + target[prop] = value; + override[prop] = value; + return true; + } + }); + } + + return override; + } + + // Only when not mixable and override hasn't been set. + return existing; + } + }); + + document.addEventListener('pjax:success', () => { + variableConfig = {}; + }); +})(); diff --git a/assets/js/motion.js b/assets/js/motion.js new file mode 100644 index 0000000..2f38249 --- /dev/null +++ b/assets/js/motion.js @@ -0,0 +1,125 @@ +/* global NexT, CONFIG */ + +NexT.motion = {}; + +NexT.motion.integrator = { + queue: [], + init : function() { + this.queue = []; + return this; + }, + add: function(fn) { + const sequence = fn(); + if (CONFIG.motion.async) this.queue.push(sequence); + else this.queue = this.queue.concat(sequence); + return this; + }, + bootstrap: function() { + if (!CONFIG.motion.async) this.queue = [this.queue]; + this.queue.forEach(sequence => { + const timeline = window.anime.timeline({ + duration: 200, + easing : 'linear' + }); + sequence.forEach(item => { + if (item.deltaT) timeline.add(item, item.deltaT); + else timeline.add(item); + }); + }); + } +}; + +NexT.motion.middleWares = { + header: function() { + const sequence = []; + + function getMistLineSettings(targets) { + sequence.push({ + targets, + scaleX : [0, 1], + duration: 500, + deltaT : '-=200' + }); + } + + function pushToSequence(targets, sequenceQueue = false) { + sequence.push({ + targets, + opacity: 1, + top : 0, + deltaT : sequenceQueue ? '-=200' : '-=0' + }); + } + + pushToSequence('header.header'); + CONFIG.scheme === 'Mist' && getMistLineSettings('.logo-line'); + CONFIG.scheme === 'Muse' && pushToSequence('.custom-logo-image'); + pushToSequence('.site-title'); + pushToSequence('.site-brand-container .toggle', true); + pushToSequence('.site-subtitle'); + (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') && pushToSequence('.custom-logo-image'); + + document.querySelectorAll('.menu-item').forEach(targets => { + sequence.push({ + targets, + complete: () => targets.classList.add('animated', 'fadeInDown'), + deltaT : '-=200' + }); + }); + + return sequence; + }, + + subMenu: function() { + const subMenuItem = document.querySelectorAll('.sub-menu .menu-item'); + if (subMenuItem.length > 0) { + subMenuItem.forEach(element => { + element.classList.add('animated'); + }); + } + return []; + }, + + postList: function() { + const sequence = []; + const { post_block, post_header, post_body, coll_header } = CONFIG.motion.transition; + + function animate(animation, selector) { + if (!animation) return; + document.querySelectorAll(selector).forEach(targets => { + sequence.push({ + targets, + complete: () => targets.classList.add('animated', animation), + deltaT : '-=100' + }); + }); + } + + animate(post_block, '.post-block, .pagination, .comments'); + animate(coll_header, '.collection-header'); + animate(post_header, '.post-header'); + animate(post_body, '.post-body'); + + return sequence; + }, + + sidebar: function() { + const sidebar = document.querySelector('.sidebar'); + const sidebarTransition = CONFIG.motion.transition.sidebar; + // Only for Pisces | Gemini. + if (sidebarTransition && (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini')) { + return [{ + targets : sidebar, + complete: () => sidebar.classList.add('animated', sidebarTransition) + }]; + } + return []; + }, + + footer: function() { + return [{ + targets: document.querySelector('.footer'), + opacity: 1 + }]; + } +}; diff --git a/assets/js/next-boot.js b/assets/js/next-boot.js new file mode 100644 index 0000000..6262daa --- /dev/null +++ b/assets/js/next-boot.js @@ -0,0 +1,75 @@ +/* global NexT, CONFIG */ + +NexT.boot = {}; + +NexT.boot.registerEvents = function() { + + NexT.utils.registerScrollPercent(); + NexT.utils.registerCanIUseTag(); + + // Mobile top menu bar. + document.querySelector('.site-nav-toggle .toggle').addEventListener('click', event => { + event.currentTarget.classList.toggle('toggle-close'); + const siteNav = document.querySelector('.site-nav'); + if (!siteNav) return; + siteNav.style.setProperty('--scroll-height', siteNav.scrollHeight + 'px'); + document.body.classList.toggle('site-nav-on'); + }); + + document.querySelectorAll('.sidebar-nav li').forEach((element, index) => { + element.addEventListener('click', () => { + NexT.utils.activateSidebarPanel(index); + }); + }); + + window.addEventListener('hashchange', () => { + const tHash = location.hash; + if (tHash !== '' && !tHash.match(/%\S{2}/)) { + const target = document.querySelector(`.tabs ul.nav-tabs li a[href="${tHash}"]`); + target && target.click(); + } + }); +}; + +NexT.boot.refresh = function() { + + /** + * Register JS handlers by condition option. + * Need to add config option in Front-End at 'scripts/helpers/next-config.js' file. + */ + CONFIG.prism && window.Prism.highlightAll(); + CONFIG.mediumzoom && window.mediumZoom('.post-body :not(a) > img, .post-body > img', { + background: 'var(--content-bg-color)' + }); + CONFIG.lazyload && window.lozad('.post-body img').observe(); + CONFIG.pangu && window.pangu.spacingPage(); + + CONFIG.exturl && NexT.utils.registerExtURL(); + NexT.utils.registerCopyCode(); + NexT.utils.registerTabsTag(); + NexT.utils.registerActiveMenuItem(); + NexT.utils.registerLangSelect(); + NexT.utils.registerSidebarTOC(); + NexT.utils.registerPostReward(); + NexT.utils.wrapTableWithBox(); + NexT.utils.registerVideoIframe(); +}; + +NexT.boot.motion = function() { + // Define Motion Sequence & Bootstrap Motion. + if (CONFIG.motion.enable) { + NexT.motion.integrator + .add(NexT.motion.middleWares.header) + .add(NexT.motion.middleWares.postList) + .add(NexT.motion.middleWares.sidebar) + .add(NexT.motion.middleWares.footer) + .bootstrap(); + } + NexT.utils.updateSidebarPosition(); +}; + +document.addEventListener('DOMContentLoaded', () => { + NexT.boot.registerEvents(); + NexT.boot.refresh(); + NexT.boot.motion(); +}); diff --git a/assets/js/pjax.js b/assets/js/pjax.js new file mode 100644 index 0000000..da61136 --- /dev/null +++ b/assets/js/pjax.js @@ -0,0 +1,34 @@ +/* global NexT, CONFIG, Pjax */ + +const pjax = new Pjax({ + selectors: [ + 'head title', + 'script[type="application/json"]', + '.main-inner', + '.post-toc-wrap', + '.languages', + '.pjax' + ], + analytics: false, + cacheBust: false, + scrollTo : !CONFIG.bookmark.enable +}); + +document.addEventListener('pjax:success', () => { + pjax.executeScripts(document.querySelectorAll('script[data-pjax]')); + NexT.boot.refresh(); + // Define Motion Sequence & Bootstrap Motion. + if (CONFIG.motion.enable) { + NexT.motion.integrator + .init() + .add(NexT.motion.middleWares.subMenu) + .add(NexT.motion.middleWares.postList) + .bootstrap(); + } + if (CONFIG.sidebar.display !== 'remove') { + const hasTOC = document.querySelector('.post-toc'); + document.querySelector('.sidebar-inner').classList.toggle('sidebar-nav-active', hasTOC); + NexT.utils.activateSidebarPanel(hasTOC ? 0 : 1); + NexT.utils.updateSidebarPosition(); + } +}); diff --git a/assets/js/schedule.js b/assets/js/schedule.js new file mode 100644 index 0000000..8f0c26c --- /dev/null +++ b/assets/js/schedule.js @@ -0,0 +1,138 @@ +/* global CONFIG */ + +// https://developers.google.com/calendar/api/v3/reference/events/list +(function() { + // Initialization + const calendar = { + orderBy : 'startTime', + showLocation: false, + offsetMax : 72, + offsetMin : 4, + showDeleted : false, + singleEvents: true, + maxResults : 250 + }; + + // Read config form theme config file + Object.assign(calendar, CONFIG.calendar); + + const now = new Date(); + const timeMax = new Date(); + const timeMin = new Date(); + + timeMax.setHours(now.getHours() + calendar.offsetMax); + timeMin.setHours(now.getHours() - calendar.offsetMin); + + // Build URL + const params = { + key : calendar.api_key, + orderBy : calendar.orderBy, + timeMax : timeMax.toISOString(), + timeMin : timeMin.toISOString(), + showDeleted : calendar.showDeleted, + singleEvents: calendar.singleEvents, + maxResults : calendar.maxResults + }; + + const request_url = new URL(`https://www.googleapis.com/calendar/v3/calendars/${calendar.calendar_id}/events`); + Object.entries(params).forEach(param => request_url.searchParams.append(...param)); + + function getRelativeTime(current, previous) { + const msPerMinute = 60 * 1000; + const msPerHour = msPerMinute * 60; + const msPerDay = msPerHour * 24; + const msPerMonth = msPerDay * 30; + const msPerYear = msPerDay * 365; + + let elapsed = current - previous; + const tense = elapsed > 0 ? ' ago' : ' later'; + + elapsed = Math.abs(elapsed); + + if (elapsed < msPerHour) { + return Math.round(elapsed / msPerMinute) + ' minutes' + tense; + } else if (elapsed < msPerDay) { + return Math.round(elapsed / msPerHour) + ' hours' + tense; + } else if (elapsed < msPerMonth) { + return 'about ' + Math.round(elapsed / msPerDay) + ' days' + tense; + } else if (elapsed < msPerYear) { + return 'about ' + Math.round(elapsed / msPerMonth) + ' months' + tense; + } + + return 'about ' + Math.round(elapsed / msPerYear) + ' years' + tense; + } + + function buildEventDOM(tense, event, start, end) { + const durationFormat = { + weekday: 'short', + hour : '2-digit', + minute : '2-digit' + }; + const relativeTime = tense === 'now' ? 'NOW' : getRelativeTime(now, start); + const duration = start.toLocaleTimeString([], durationFormat) + ' - ' + end.toLocaleTimeString([], durationFormat); + + let location = ''; + if (calendar.showLocation && event.location) { + location = `${event.location}`; + } + let description = ''; + if (event.description) { + description = `${event.description}`; + } + + const eventContent = `
+

+ ${event.summary} + ${relativeTime} +

+ ${location} + ${duration} + ${description} +
`; + return eventContent; + } + + function fetchData() { + const eventList = document.querySelector('.event-list'); + if (!eventList) return; + + fetch(request_url.href).then(response => { + return response.json(); + }).then(data => { + if (data.items.length === 0) { + eventList.innerHTML = '
'; + return; + } + // Clean the event list + eventList.innerHTML = ''; + let prevEnd = 0; // used to decide where to insert an
+ const utc = new Date().getTimezoneOffset() * 60000; + + data.items.forEach(event => { + // Parse data + const start = new Date(event.start.dateTime || (new Date(event.start.date).getTime() + utc)); + const end = new Date(event.end.dateTime || (new Date(event.end.date).getTime() + utc)); + + let tense = 'now'; + if (end < now) { + tense = 'past'; + } else if (start > now) { + tense = 'future'; + } + + if (tense === 'future' && prevEnd < now) { + eventList.insertAdjacentHTML('beforeend', '
'); + } + + eventList.insertAdjacentHTML('beforeend', buildEventDOM(tense, event, start, end)); + prevEnd = end; + }); + }); + } + + fetchData(); + const fetchDataTimer = setInterval(fetchData, 60000); + document.addEventListener('pjax:send', () => { + clearInterval(fetchDataTimer); + }); +})(); diff --git a/assets/js/schemes/muse.js b/assets/js/schemes/muse.js new file mode 100644 index 0000000..ae5addb --- /dev/null +++ b/assets/js/schemes/muse.js @@ -0,0 +1,60 @@ +/* global CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + + const isRight = CONFIG.sidebar.position === 'right'; + + const sidebarToggleMotion = { + mouse: {}, + init : function() { + window.addEventListener('mousedown', this.mousedownHandler.bind(this)); + window.addEventListener('mouseup', this.mouseupHandler.bind(this)); + document.querySelector('.sidebar-dimmer').addEventListener('click', this.clickHandler.bind(this)); + document.querySelector('.sidebar-toggle').addEventListener('click', this.clickHandler.bind(this)); + window.addEventListener('sidebar:show', this.showSidebar); + window.addEventListener('sidebar:hide', this.hideSidebar); + }, + mousedownHandler: function(event) { + this.mouse.X = event.pageX; + this.mouse.Y = event.pageY; + }, + mouseupHandler: function(event) { + const deltaX = event.pageX - this.mouse.X; + const deltaY = event.pageY - this.mouse.Y; + const clickingBlankPart = Math.hypot(deltaX, deltaY) < 20 && event.target.matches('.main'); + // Fancybox has z-index property, but medium-zoom does not, so the sidebar will overlay the zoomed image. + if (clickingBlankPart || event.target.matches('img.medium-zoom-image')) { + this.hideSidebar(); + } + }, + clickHandler: function() { + document.body.classList.contains('sidebar-active') ? this.hideSidebar() : this.showSidebar(); + }, + showSidebar: function() { + document.body.classList.add('sidebar-active'); + const animateAction = isRight ? 'fadeInRight' : 'fadeInLeft'; + document.querySelectorAll('.sidebar .animated').forEach((element, index) => { + element.style.animationDelay = (100 * index) + 'ms'; + element.classList.remove(animateAction); + setTimeout(() => { + // Trigger a DOM reflow + element.classList.add(animateAction); + }); + }); + }, + hideSidebar: function() { + document.body.classList.remove('sidebar-active'); + } + }; + if (CONFIG.sidebar.display !== 'remove') sidebarToggleMotion.init(); + + function updateFooterPosition() { + const footer = document.querySelector('.footer'); + const containerHeight = document.querySelector('header.header').offsetHeight + document.querySelector('.main').offsetHeight + footer.offsetHeight; + footer.classList.toggle('footer-fixed', containerHeight <= window.innerHeight); + } + + updateFooterPosition(); + window.addEventListener('resize', updateFooterPosition); + window.addEventListener('scroll', updateFooterPosition, { passive: true }); +}); diff --git a/assets/js/third-party/analytics/baidu-analytics.js b/assets/js/third-party/analytics/baidu-analytics.js new file mode 100644 index 0000000..c10e7d0 --- /dev/null +++ b/assets/js/third-party/analytics/baidu-analytics.js @@ -0,0 +1,7 @@ +/* global _hmt */ + +if (!window._hmt) window._hmt = []; + +document.addEventListener('pjax:success', () => { + _hmt.push(['_trackPageview', location.pathname]); +}); diff --git a/assets/js/third-party/analytics/google-analytics.js b/assets/js/third-party/analytics/google-analytics.js new file mode 100644 index 0000000..2cd128f --- /dev/null +++ b/assets/js/third-party/analytics/google-analytics.js @@ -0,0 +1,35 @@ +/* global CONFIG, dataLayer, gtag */ + +if (!CONFIG.google_analytics.only_pageview) { + if (CONFIG.hostname === location.hostname) { + window.dataLayer = window.dataLayer || []; + window.gtag = function() { + dataLayer.push(arguments); + }; + gtag('js', new Date()); + gtag('config', CONFIG.google_analytics.tracking_id); + + document.addEventListener('pjax:success', () => { + gtag('event', 'page_view', { + page_location: location.href, + page_path : location.pathname, + page_title : document.title + }); + }); + } +} else { + const sendPageView = () => { + if (CONFIG.hostname !== location.hostname) return; + const uid = localStorage.getItem('uid') || (Math.random() + '.' + Math.random()); + localStorage.setItem('uid', uid); + navigator.sendBeacon('https://www.google-analytics.com/collect', new URLSearchParams({ + v : 1, + tid: CONFIG.google_analytics.tracking_id, + cid: uid, + t : 'pageview', + dp : encodeURIComponent(location.pathname) + })); + }; + document.addEventListener('pjax:complete', sendPageView); + sendPageView(); +} diff --git a/assets/js/third-party/analytics/growingio.js b/assets/js/third-party/analytics/growingio.js new file mode 100644 index 0000000..0460833 --- /dev/null +++ b/assets/js/third-party/analytics/growingio.js @@ -0,0 +1,10 @@ +/* global CONFIG, gio */ + +if (!window.gio) { + window.gio = function() { + (window.gio.q = window.gio.q || []).push(arguments); + }; +} + +gio('init', `${CONFIG.growingio_analytics}`, {}); +gio('send'); diff --git a/assets/js/third-party/chat/chatra.js b/assets/js/third-party/chat/chatra.js new file mode 100644 index 0000000..e495b8e --- /dev/null +++ b/assets/js/third-party/chat/chatra.js @@ -0,0 +1,19 @@ +/* global CONFIG, Chatra */ + +(function() { + if (CONFIG.chatra.embed) { + window.ChatraSetup = { + mode : 'frame', + injectTo: CONFIG.chatra.embed + }; + } + + window.ChatraID = CONFIG.chatra.id; + + const chatButton = document.querySelector('.sidebar-button button'); + if (chatButton) { + chatButton.addEventListener('click', () => { + Chatra('openChat', true); + }); + } +})(); diff --git a/assets/js/third-party/chat/gitter.js b/assets/js/third-party/chat/gitter.js new file mode 100644 index 0000000..2b26d05 --- /dev/null +++ b/assets/js/third-party/chat/gitter.js @@ -0,0 +1,5 @@ +/* global CONFIG */ + +((window.gitter = {}).chat = {}).options = { + room: CONFIG.gitter.room +}; diff --git a/assets/js/third-party/chat/tidio.js b/assets/js/third-party/chat/tidio.js new file mode 100644 index 0000000..bffb918 --- /dev/null +++ b/assets/js/third-party/chat/tidio.js @@ -0,0 +1,10 @@ +/* global tidioChatApi */ + +(function() { + const chatButton = document.querySelector('.sidebar-button button'); + if (chatButton) { + chatButton.addEventListener('click', () => { + tidioChatApi.open(); + }); + } +})(); diff --git a/assets/js/third-party/comments/changyan.js b/assets/js/third-party/comments/changyan.js new file mode 100644 index 0000000..18a1be4 --- /dev/null +++ b/assets/js/third-party/comments/changyan.js @@ -0,0 +1,39 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + const { appid, appkey } = CONFIG.changyan; + const mainJs = 'https://cy-cdn.kuaizhan.com/upload/changyan.js'; + const countJs = `https://cy-cdn.kuaizhan.com/upload/plugins/plugins.list.count.js?clientId=${appid}`; + + // Get the number of comments + setTimeout(() => { + return NexT.utils.getScript(countJs, { + attributes: { + async: true, + id : 'cy_cmt_num' + } + }); + }, 0); + + // When scroll to comment section + if (CONFIG.page.comments && !CONFIG.page.isHome) { + NexT.utils.loadComments('#SOHUCS') + .then(() => { + return NexT.utils.getScript(mainJs, { + attributes: { + async: true + } + }); + }) + .then(() => { + window.changyan.api.config({ + appid, + conf: appkey + }); + }) + .catch(error => { + // eslint-disable-next-line no-console + console.error('Failed to load Changyan', error); + }); + } +}); diff --git a/assets/js/third-party/comments/disqus.js b/assets/js/third-party/comments/disqus.js new file mode 100644 index 0000000..381c26f --- /dev/null +++ b/assets/js/third-party/comments/disqus.js @@ -0,0 +1,41 @@ +/* global NexT, CONFIG, DISQUS */ + +document.addEventListener('page:loaded', () => { + + if (CONFIG.disqus.count) { + const loadCount = () => { + NexT.utils.getScript(`https://${CONFIG.disqus.shortname}.disqus.com/count.js`, { + attributes: { id: 'dsq-count-scr' } + }); + }; + + // defer loading until the whole page loading is completed + window.addEventListener('load', loadCount, false); + } + + if (CONFIG.page.comments) { + // `disqus_config` should be a global variable + // See https://help.disqus.com/en/articles/1717084-javascript-configuration-variables + window.disqus_config = function() { + this.page.url = CONFIG.page.permalink; + this.page.identifier = CONFIG.page.path; + this.page.title = CONFIG.page.title; + if (CONFIG.disqus.i18n.disqus !== 'disqus') { + this.language = CONFIG.disqus.i18n.disqus; + } + }; + NexT.utils.loadComments('#disqus_thread').then(() => { + if (window.DISQUS) { + DISQUS.reset({ + reload: true, + config: window.disqus_config + }); + } else { + NexT.utils.getScript(`https://${CONFIG.disqus.shortname}.disqus.com/embed.js`, { + attributes: { dataset: { timestamp: '' + +new Date() } } + }); + } + }); + } + +}); diff --git a/assets/js/third-party/comments/disqusjs.js b/assets/js/third-party/comments/disqusjs.js new file mode 100644 index 0000000..df5f36c --- /dev/null +++ b/assets/js/third-party/comments/disqusjs.js @@ -0,0 +1,18 @@ +/* global NexT, CONFIG, DisqusJS */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('#disqus_thread') + .then(() => NexT.utils.getScript(CONFIG.disqusjs.js, { condition: window.DisqusJS })) + .then(() => { + window.dsqjs = new DisqusJS({ + api : CONFIG.disqusjs.api || 'https://disqus.com/api/', + apikey : CONFIG.disqusjs.apikey, + shortname : CONFIG.disqusjs.shortname, + url : CONFIG.page.permalink, + identifier: CONFIG.page.path, + title : CONFIG.page.title + }); + }); +}); diff --git a/assets/js/third-party/comments/gitalk.js b/assets/js/third-party/comments/gitalk.js new file mode 100644 index 0000000..08d07f4 --- /dev/null +++ b/assets/js/third-party/comments/gitalk.js @@ -0,0 +1,24 @@ +/* global NexT, CONFIG, Gitalk */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('.gitalk-container') + .then(() => NexT.utils.getScript(CONFIG.gitalk.js, { + condition: window.Gitalk + })) + .then(() => { + const gitalk = new Gitalk({ + clientID : CONFIG.gitalk.client_id, + clientSecret : CONFIG.gitalk.client_secret, + repo : CONFIG.gitalk.repo, + owner : CONFIG.gitalk.github_id, + admin : [CONFIG.gitalk.admin_user], + id : CONFIG.gitalk.path_md5, + proxy : CONFIG.gitalk.proxy, + language : CONFIG.gitalk.language || window.navigator.language, + distractionFreeMode: CONFIG.gitalk.distraction_free_mode + }); + gitalk.render(document.querySelector('.gitalk-container')); + }); +}); diff --git a/assets/js/third-party/comments/isso.js b/assets/js/third-party/comments/isso.js new file mode 100644 index 0000000..2c70601 --- /dev/null +++ b/assets/js/third-party/comments/isso.js @@ -0,0 +1,15 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('#isso-thread') + .then(() => NexT.utils.getScript(`${CONFIG.isso}js/embed.min.js`, { + attributes: { + dataset: { + isso: `${CONFIG.isso}` + } + }, + parentNode: document.querySelector('#isso-thread') + })); +}); diff --git a/assets/js/third-party/comments/livere.js b/assets/js/third-party/comments/livere.js new file mode 100644 index 0000000..c4bcd2e --- /dev/null +++ b/assets/js/third-party/comments/livere.js @@ -0,0 +1,19 @@ +/* global NexT, CONFIG, LivereTower */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('#lv-container').then(() => { + window.livereOptions = { + refer: CONFIG.page.path.replace(/index\.html$/, '') + }; + + if (typeof LivereTower === 'function') return; + + NexT.utils.getScript('https://cdn-city.livere.com/js/embed.dist.js', { + attributes: { + async: true + } + }); + }); +}); diff --git a/assets/js/third-party/comments/utterances.js b/assets/js/third-party/comments/utterances.js new file mode 100644 index 0000000..332ee05 --- /dev/null +++ b/assets/js/third-party/comments/utterances.js @@ -0,0 +1,17 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('.utterances-container') + .then(() => NexT.utils.getScript('https://utteranc.es/client.js', { + attributes: { + async : true, + crossOrigin : 'anonymous', + 'repo' : CONFIG.utterances.repo, + 'issue-term': CONFIG.utterances.issue_term, + 'theme' : CONFIG.utterances.theme + }, + parentNode: document.querySelector('.utterances-container') + })); +}); diff --git a/assets/js/third-party/fancybox.js b/assets/js/third-party/fancybox.js new file mode 100644 index 0000000..bb436ab --- /dev/null +++ b/assets/js/third-party/fancybox.js @@ -0,0 +1,38 @@ +document.addEventListener('page:loaded', () => { + + /** + * Wrap images with fancybox. + */ + document.querySelectorAll('.post-body :not(a) > img, .post-body > img').forEach(element => { + const $image = $(element); + const imageLink = $image.attr('data-src') || $image.attr('src'); + const $imageWrapLink = $image.wrap(``).parent('a'); + if ($image.is('.post-gallery img')) { + $imageWrapLink.attr('data-fancybox', 'gallery').attr('rel', 'gallery'); + } else if ($image.is('.group-picture img')) { + $imageWrapLink.attr('data-fancybox', 'group').attr('rel', 'group'); + } else { + $imageWrapLink.attr('data-fancybox', 'default').attr('rel', 'default'); + } + + const imageTitle = $image.attr('title') || $image.attr('alt'); + if (imageTitle) { + // Do not append image-caption if pandoc has already created a figcaption + if (!$imageWrapLink.next('figcaption').length) { + $imageWrapLink.append(`

${imageTitle}

`); + } + // Make sure img title tag will show correctly in fancybox + $imageWrapLink.attr('title', imageTitle).attr('data-caption', imageTitle); + } + }); + + $.fancybox.defaults.hash = false; + $('.fancybox').fancybox({ + loop : true, + helpers: { + overlay: { + locked: false + } + } + }); +}); diff --git a/assets/js/third-party/math/katex.js b/assets/js/third-party/math/katex.js new file mode 100644 index 0000000..ad745b1 --- /dev/null +++ b/assets/js/third-party/math/katex.js @@ -0,0 +1,7 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.enableMath) return; + + NexT.utils.getScript(CONFIG.katex.copy_tex_js).catch(() => {}); +}); diff --git a/assets/js/third-party/math/mathjax.js b/assets/js/third-party/math/mathjax.js new file mode 100644 index 0000000..fe4d448 --- /dev/null +++ b/assets/js/third-party/math/mathjax.js @@ -0,0 +1,36 @@ +/* global NexT, CONFIG, MathJax */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.enableMath) return; + + if (typeof MathJax === 'undefined') { + window.MathJax = { + tex: { + inlineMath: { '[+]': [['$', '$']] }, + tags : CONFIG.mathjax.tags + }, + options: { + renderActions: { + insertedScript: [200, () => { + document.querySelectorAll('mjx-container').forEach(node => { + const target = node.parentNode; + if (target.nodeName.toLowerCase() === 'li') { + target.parentNode.classList.add('has-jax'); + } + }); + }, '', false] + } + } + }; + NexT.utils.getScript(CONFIG.mathjax.js, { + attributes: { + defer: true + } + }); + } else { + MathJax.startup.document.state(0); + MathJax.typesetClear(); + MathJax.texReset(); + MathJax.typesetPromise(); + } +}); diff --git a/assets/js/third-party/pace.js b/assets/js/third-party/pace.js new file mode 100644 index 0000000..c22d59f --- /dev/null +++ b/assets/js/third-party/pace.js @@ -0,0 +1,7 @@ +/* global Pace */ + +Pace.options.restartOnPushState = false; + +document.addEventListener('pjax:send', () => { + Pace.restart(); +}); diff --git a/assets/js/third-party/quicklink.js b/assets/js/third-party/quicklink.js new file mode 100644 index 0000000..2543ad1 --- /dev/null +++ b/assets/js/third-party/quicklink.js @@ -0,0 +1,37 @@ +/* global CONFIG, quicklink */ + +(function() { + if (typeof CONFIG.quicklink.ignores === 'string') { + const ignoresStr = `[${CONFIG.quicklink.ignores}]`; + CONFIG.quicklink.ignores = JSON.parse(ignoresStr); + } + + let resetFn = null; + + const onRefresh = () => { + if (resetFn) resetFn(); + if (!CONFIG.quicklink.enable) return; + + let ignoresArr = CONFIG.quicklink.ignores || []; + if (!Array.isArray(ignoresArr)) { + ignoresArr = [ignoresArr]; + } + + resetFn = quicklink.listen({ + timeout : CONFIG.quicklink.timeout, + priority: CONFIG.quicklink.priority, + ignores : [ + uri => uri.includes('#'), + uri => uri === CONFIG.quicklink.url, + ...ignoresArr + ] + }); + }; + + if (CONFIG.quicklink.delay) { + window.addEventListener('load', onRefresh); + document.addEventListener('pjax:success', onRefresh); + } else { + document.addEventListener('page:loaded', onRefresh); + } +})(); diff --git a/assets/js/third-party/rating.js b/assets/js/third-party/rating.js new file mode 100644 index 0000000..fc61a3a --- /dev/null +++ b/assets/js/third-party/rating.js @@ -0,0 +1,22 @@ +/* global CONFIG, WPac */ + +(function() { + const widgets = [{ + widget: 'Rating', + id : CONFIG.rating.id, + el : 'wpac-rating', + color : CONFIG.rating.color + }]; + + document.addEventListener('page:loaded', () => { + if (!CONFIG.page.isPost) return; + + const newWidgets = widgets.map(widget => ({ ...widget })); + + if (window.WPac) { + WPac.init(newWidgets); + } else { + window.wpac_init = newWidgets; + } + }); +})(); diff --git a/assets/js/third-party/search/algolia-search.js b/assets/js/third-party/search/algolia-search.js new file mode 100644 index 0000000..12a554c --- /dev/null +++ b/assets/js/third-party/search/algolia-search.js @@ -0,0 +1,130 @@ +/* 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/local-search.js b/assets/js/third-party/search/local-search.js new file mode 100644 index 0000000..92a264d --- /dev/null +++ b/assets/js/third-party/search/local-search.js @@ -0,0 +1,99 @@ +/* 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}
+
+ `; + 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/assets/js/third-party/statistics/firestore.js b/assets/js/third-party/statistics/firestore.js new file mode 100644 index 0000000..b06dbb1 --- /dev/null +++ b/assets/js/third-party/statistics/firestore.js @@ -0,0 +1,64 @@ +/* global CONFIG, firebase */ + +firebase.initializeApp({ + apiKey : CONFIG.firestore.apiKey, + projectId: CONFIG.firestore.projectId +}); + +(function() { + const getCount = (doc, increaseCount) => { + // IncreaseCount will be false when not in article page + return doc.get().then(d => { + // Has no data, initialize count + let count = d.exists ? d.data().count : 0; + // If first view this article + if (increaseCount) { + // Increase count + count++; + doc.set({ + count + }); + } + return count; + }); + }; + + const appendCountTo = el => { + return count => { + el.innerText = count; + }; + }; + + const db = firebase.firestore(); + const articles = db.collection(CONFIG.firestore.collection); + + document.addEventListener('page:loaded', () => { + + if (CONFIG.page.isPost) { + // Fix issue #118 + // https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent + const title = document.querySelector('.post-title').textContent.trim(); + const doc = articles.doc(title); + let increaseCount = CONFIG.hostname === location.hostname; + if (localStorage.getItem(title)) { + increaseCount = false; + } else { + // Mark as visited + localStorage.setItem(title, true); + } + getCount(doc, increaseCount).then(appendCountTo(document.querySelector('.firestore-visitors-count'))); + } else if (CONFIG.page.isHome) { + const promises = [...document.querySelectorAll('.post-title')].map(element => { + const title = element.textContent.trim(); + const doc = articles.doc(title); + return getCount(doc); + }); + Promise.all(promises).then(counts => { + const metas = document.querySelectorAll('.firestore-visitors-count'); + counts.forEach((val, idx) => { + appendCountTo(metas[idx])(val); + }); + }); + } + }); +})(); diff --git a/assets/js/third-party/statistics/lean-analytics.js b/assets/js/third-party/statistics/lean-analytics.js new file mode 100644 index 0000000..b5d4205 --- /dev/null +++ b/assets/js/third-party/statistics/lean-analytics.js @@ -0,0 +1,102 @@ +/* global CONFIG */ +/* eslint-disable no-console */ + +(function() { + const leancloudSelector = url => { + url = encodeURI(url); + return document.getElementById(url).querySelector('.leancloud-visitors-count'); + }; + + const addCount = Counter => { + const visitors = document.querySelector('.leancloud_visitors'); + const url = decodeURI(visitors.id); + const title = visitors.dataset.flagTitle; + + Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({ url }))}`) + .then(response => response.json()) + .then(({ results }) => { + if (results.length > 0) { + const counter = results[0]; + leancloudSelector(url).innerText = counter.time + 1; + Counter('put', '/classes/Counter/' + counter.objectId, { + time: { + '__op' : 'Increment', + 'amount': 1 + } + }) + .catch(error => { + console.error('Failed to save visitor count', error); + }); + } else if (CONFIG.leancloud_visitors.security) { + leancloudSelector(url).innerText = 'Counter not initialized! More info at console err msg.'; + console.error('ATTENTION! LeanCloud counter has security bug, see how to solve it here: https://github.com/theme-next/hexo-leancloud-counter-security. \n However, you can still use LeanCloud without security, by setting `security` option to `false`.'); + } else { + Counter('post', '/classes/Counter', { title, url, time: 1 }) + .then(response => response.json()) + .then(() => { + leancloudSelector(url).innerText = 1; + }) + .catch(error => { + console.error('Failed to create', error); + }); + } + }) + .catch(error => { + console.error('LeanCloud Counter Error', error); + }); + }; + + const showTime = Counter => { + const visitors = document.querySelectorAll('.leancloud_visitors'); + const entries = [...visitors].map(element => { + return decodeURI(element.id); + }); + + Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({ url: { '$in': entries } }))}`) + .then(response => response.json()) + .then(({ results }) => { + for (const url of entries) { + const target = results.find(item => item.url === url); + leancloudSelector(url).innerText = target ? target.time : 0; + } + }) + .catch(error => { + console.error('LeanCloud Counter Error', error); + }); + }; + + const { app_id, app_key, server_url } = CONFIG.leancloud_visitors; + const fetchData = api_server => { + const Counter = (method, url, data) => { + return fetch(`${api_server}/1.1${url}`, { + method, + headers: { + 'X-LC-Id' : app_id, + 'X-LC-Key' : app_key, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + }; + if (CONFIG.page.isPost) { + if (CONFIG.hostname !== location.hostname) return; + addCount(Counter); + } else if (document.querySelectorAll('.post-title-link').length >= 1) { + showTime(Counter); + } + }; + + const api_server = app_id.slice(-9) === '-MdYXbMMI' ? `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com` : server_url; + + document.addEventListener('page:loaded', () => { + if (api_server) { + fetchData(api_server); + } else { + fetch(`https://app-router.leancloud.cn/2/route?appId=${app_id}`) + .then(response => response.json()) + .then(({ api_server }) => { + fetchData(`https://${api_server}`); + }); + } + }); +})(); diff --git a/assets/js/third-party/tags/mermaid.js b/assets/js/third-party/tags/mermaid.js new file mode 100644 index 0000000..9623dc5 --- /dev/null +++ b/assets/js/third-party/tags/mermaid.js @@ -0,0 +1,32 @@ +/* global NexT, CONFIG, mermaid */ + +document.addEventListener('page:loaded', () => { + const mermaidElements = document.querySelectorAll('.mermaid'); + if (mermaidElements.length) { + NexT.utils.getScript(CONFIG.mermaid.js, { + condition: window.mermaid + }).then(() => { + mermaidElements.forEach(element => { + const newElement = document.createElement('div'); + newElement.innerHTML = element.innerHTML; + newElement.className = element.className; + const parent = element.parentNode; + // Fix issue #347 + // Support mermaid inside backtick code block + if (parent.matches('pre')) { + parent.parentNode.replaceChild(newElement, parent); + } else { + parent.replaceChild(newElement, element); + } + }); + mermaid.initialize({ + theme : CONFIG.darkmode && window.matchMedia('(prefers-color-scheme: dark)').matches ? CONFIG.mermaid.theme.dark : CONFIG.mermaid.theme.light, + logLevel : 4, + flowchart: { curve: 'linear' }, + gantt : { axisFormat: '%m/%d/%Y' }, + sequence : { actorMargin: 50 } + }); + mermaid.init(); + }); + } +}); diff --git a/assets/js/third-party/tags/pdf.js b/assets/js/third-party/tags/pdf.js new file mode 100644 index 0000000..7e82891 --- /dev/null +++ b/assets/js/third-party/tags/pdf.js @@ -0,0 +1,23 @@ +/* global NexT, CONFIG, PDFObject */ + +document.addEventListener('page:loaded', () => { + if (document.querySelectorAll('.pdf-container').length) { + NexT.utils.getScript(CONFIG.pdf.object_url, { + condition: window.PDFObject + }).then(() => { + document.querySelectorAll('.pdf-container').forEach(element => { + PDFObject.embed(element.dataset.target, element, { + pdfOpenParams: { + navpanes : 0, + toolbar : 0, + statusbar: 0, + pagemode : 'thumbs', + view : 'FitH' + }, + PDFJS_URL: CONFIG.pdf.url, + height : element.dataset.height + }); + }); + }); + } +}); diff --git a/assets/js/utils.js b/assets/js/utils.js new file mode 100644 index 0000000..0a0665b --- /dev/null +++ b/assets/js/utils.js @@ -0,0 +1,399 @@ +/* global NexT, CONFIG */ + +HTMLElement.prototype.wrap = function(wrapper) { + this.parentNode.insertBefore(wrapper, this); + this.parentNode.removeChild(this); + wrapper.appendChild(this); +}; + +(function() { + const onPageLoaded = () => document.dispatchEvent( + new Event('page:loaded', { + bubbles: true + }) + ); + + if (document.readyState === 'loading') { + document.addEventListener('readystatechange', onPageLoaded, { once: true }); + } else { + onPageLoaded(); + } + document.addEventListener('pjax:success', onPageLoaded); +})(); + +NexT.utils = { + + registerExtURL: function() { + document.querySelectorAll('span.exturl').forEach(element => { + const link = document.createElement('a'); + // https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings + link.href = decodeURIComponent(atob(element.dataset.url).split('').map(c => { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); + link.rel = 'noopener external nofollow noreferrer'; + link.target = '_blank'; + link.className = element.className; + link.title = element.title; + link.innerHTML = element.innerHTML; + element.parentNode.replaceChild(link, element); + }); + }, + + /** + * One-click copy code support. + */ + registerCopyCode: function() { + let figure = document.querySelectorAll('figure.highlight'); + if (figure.length === 0) figure = document.querySelectorAll('pre:not(.mermaid)'); + figure.forEach(element => { + element.querySelectorAll('.code .line span').forEach(span => { + span.classList.forEach(name => { + span.classList.replace(name, `hljs-${name}`); + }); + }); + if (!CONFIG.copycode) return; + element.insertAdjacentHTML('beforeend', '
'); + const button = element.querySelector('.copy-btn'); + button.addEventListener('click', () => { + const lines = element.querySelector('.code') || element.querySelector('code'); + const code = lines.innerText; + if (navigator.clipboard) { + // https://caniuse.com/mdn-api_clipboard_writetext + navigator.clipboard.writeText(code).then(() => { + button.querySelector('i').className = 'fa fa-check-circle fa-fw'; + }, () => { + button.querySelector('i').className = 'fa fa-times-circle fa-fw'; + }); + } else { + const ta = document.createElement('textarea'); + ta.style.top = window.scrollY + 'px'; // Prevent page scrolling + ta.style.position = 'absolute'; + ta.style.opacity = '0'; + ta.readOnly = true; + ta.value = code; + document.body.append(ta); + ta.select(); + ta.setSelectionRange(0, code.length); + ta.readOnly = false; + const result = document.execCommand('copy'); + button.querySelector('i').className = result ? 'fa fa-check-circle fa-fw' : 'fa fa-times-circle fa-fw'; + ta.blur(); // For iOS + button.blur(); + document.body.removeChild(ta); + } + }); + element.addEventListener('mouseleave', () => { + setTimeout(() => { + button.querySelector('i').className = 'fa fa-copy fa-fw'; + }, 300); + }); + }); + }, + + wrapTableWithBox: function() { + document.querySelectorAll('table').forEach(element => { + const box = document.createElement('div'); + box.className = 'table-container'; + element.wrap(box); + }); + }, + + registerVideoIframe: function() { + document.querySelectorAll('iframe').forEach(element => { + const supported = [ + 'www.youtube.com', + 'player.vimeo.com', + 'player.youku.com', + 'player.bilibili.com', + 'www.tudou.com' + ].some(host => element.src.includes(host)); + if (supported && !element.parentNode.matches('.video-container')) { + const box = document.createElement('div'); + box.className = 'video-container'; + element.wrap(box); + const width = Number(element.width); + const height = Number(element.height); + if (width && height) { + box.style.paddingTop = (height / width * 100) + '%'; + } + } + }); + }, + + registerScrollPercent: function() { + const backToTop = document.querySelector('.back-to-top'); + const readingProgressBar = document.querySelector('.reading-progress-bar'); + // For init back to top in sidebar if page was scrolled after page refresh. + window.addEventListener('scroll', () => { + if (backToTop || readingProgressBar) { + const contentHeight = document.body.scrollHeight - window.innerHeight; + const scrollPercent = contentHeight > 0 ? Math.min(100 * window.scrollY / contentHeight, 100) : 0; + if (backToTop) { + backToTop.classList.toggle('back-to-top-on', Math.round(scrollPercent) >= 5); + backToTop.querySelector('span').innerText = Math.round(scrollPercent) + '%'; + } + if (readingProgressBar) { + readingProgressBar.style.setProperty('--progress', scrollPercent.toFixed(2) + '%'); + } + } + if (!Array.isArray(NexT.utils.sections)) return; + let index = NexT.utils.sections.findIndex(element => { + return element && element.getBoundingClientRect().top > 10; + }); + if (index === -1) { + index = NexT.utils.sections.length - 1; + } else if (index > 0) { + index--; + } + this.activateNavByIndex(index); + }, { passive: true }); + + backToTop && backToTop.addEventListener('click', () => { + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: 0 + }); + }); + }, + + /** + * Tabs tag listener (without twitter bootstrap). + */ + registerTabsTag: function() { + // Binding `nav-tabs` & `tab-content` by real time permalink changing. + document.querySelectorAll('.tabs ul.nav-tabs .tab').forEach(element => { + element.addEventListener('click', event => { + event.preventDefault(); + // Prevent selected tab to select again. + if (element.classList.contains('active')) return; + const nav = element.parentNode; + // Add & Remove active class on `nav-tabs` & `tab-content`. + [...nav.children].forEach(target => { + target.classList.toggle('active', target === element); + }); + // https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers + const tActive = document.getElementById(element.querySelector('a').getAttribute('href').replace('#', '')); + [...tActive.parentNode.children].forEach(target => { + target.classList.toggle('active', target === tActive); + }); + // Trigger event + tActive.dispatchEvent(new Event('tabs:click', { + bubbles: true + })); + if (!CONFIG.stickytabs) return; + const offset = nav.parentNode.getBoundingClientRect().top + window.scrollY + 10; + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: offset + }); + }); + }); + + window.dispatchEvent(new Event('tabs:register')); + }, + + registerCanIUseTag: function() { + // Get responsive height passed from iframe. + window.addEventListener('message', ({ data }) => { + if (typeof data === 'string' && data.includes('ciu_embed')) { + const featureID = data.split(':')[1]; + const height = data.split(':')[2]; + document.querySelector(`iframe[data-feature=${featureID}]`).style.height = parseInt(height, 10) + 5 + 'px'; + } + }, false); + }, + + registerActiveMenuItem: function() { + document.querySelectorAll('.menu-item a[href]').forEach(target => { + const isSamePath = target.pathname === location.pathname || target.pathname === location.pathname.replace('index.html', ''); + const isSubPath = !CONFIG.root.startsWith(target.pathname) && location.pathname.startsWith(target.pathname); + target.classList.toggle('menu-item-active', target.hostname === location.hostname && (isSamePath || isSubPath)); + }); + }, + + registerLangSelect: function() { + const selects = document.querySelectorAll('.lang-select'); + selects.forEach(sel => { + sel.value = CONFIG.page.lang; + sel.addEventListener('change', () => { + const target = sel.options[sel.selectedIndex]; + document.querySelectorAll('.lang-select-label span').forEach(span => { + span.innerText = target.text; + }); + // Disable Pjax to force refresh translation of menu item + window.location.href = target.dataset.href; + }); + }); + }, + + registerSidebarTOC: function() { + this.sections = [...document.querySelectorAll('.post-toc li a.nav-link')].map(element => { + const target = document.getElementById(decodeURI(element.getAttribute('href')).replace('#', '')); + // TOC item animation navigate. + element.addEventListener('click', event => { + event.preventDefault(); + const offset = target.getBoundingClientRect().top + window.scrollY; + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: offset, + complete : () => { + history.pushState(null, document.title, element.href); + } + }); + }); + return target; + }); + }, + + registerPostReward: function() { + const button = document.querySelector('.reward-container button'); + if (!button) return; + button.addEventListener('click', () => { + document.querySelector('.post-reward').classList.toggle('active'); + }); + }, + + activateNavByIndex: function(index) { + const target = document.querySelectorAll('.post-toc li a.nav-link')[index]; + if (!target || target.classList.contains('active-current')) return; + + document.querySelectorAll('.post-toc .active').forEach(element => { + element.classList.remove('active', 'active-current'); + }); + target.classList.add('active', 'active-current'); + let parent = target.parentNode; + while (!parent.matches('.post-toc')) { + if (parent.matches('li')) parent.classList.add('active'); + parent = parent.parentNode; + } + // Scrolling to center active TOC element if TOC content is taller then viewport. + const tocElement = document.querySelector('.sidebar-panel-container'); + if (!tocElement.parentNode.classList.contains('sidebar-toc-active')) return; + window.anime({ + targets : tocElement, + duration : 200, + easing : 'linear', + scrollTop: tocElement.scrollTop - (tocElement.offsetHeight / 2) + target.getBoundingClientRect().top - tocElement.getBoundingClientRect().top + }); + }, + + updateSidebarPosition: function() { + if (window.innerWidth < 992 || CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') return; + // Expand sidebar on post detail page by default, when post has a toc. + const hasTOC = document.querySelector('.post-toc'); + let display = CONFIG.page.sidebar; + if (typeof display !== 'boolean') { + // There's no definition sidebar in the page front-matter. + display = CONFIG.sidebar.display === 'always' || (CONFIG.sidebar.display === 'post' && hasTOC); + } + if (display) { + window.dispatchEvent(new Event('sidebar:show')); + } + }, + + activateSidebarPanel: function(index) { + const duration = 200; + const sidebar = document.querySelector('.sidebar-inner'); + const panel = document.querySelector('.sidebar-panel-container'); + const activeClassName = ['sidebar-toc-active', 'sidebar-overview-active']; + + if (sidebar.classList.contains(activeClassName[index])) return; + + window.anime({ + duration, + targets : panel, + easing : 'linear', + opacity : 0, + translateY: [0, -20], + complete : () => { + // Prevent adding TOC to Overview if Overview was selected when close & open sidebar. + sidebar.classList.replace(activeClassName[1 - index], activeClassName[index]); + window.anime({ + duration, + targets : panel, + easing : 'linear', + opacity : [0, 1], + translateY: [-20, 0] + }); + } + }); + }, + + getScript: function(src, options = {}, legacyCondition) { + if (typeof options === 'function') { + return this.getScript(src, { + condition: legacyCondition + }).then(options); + } + const { + condition = false, + attributes: { + id = '', + async = false, + defer = false, + crossOrigin = '', + dataset = {}, + ...otherAttributes + } = {}, + parentNode = null + } = options; + return new Promise((resolve, reject) => { + if (condition) { + resolve(); + } else { + const script = document.createElement('script'); + + if (id) script.id = id; + if (crossOrigin) script.crossOrigin = crossOrigin; + script.async = async; + script.defer = defer; + Object.assign(script.dataset, dataset); + Object.entries(otherAttributes).forEach(([name, value]) => { + script.setAttribute(name, String(value)); + }); + + script.onload = resolve; + script.onerror = reject; + + if (typeof src === 'object') { + const { url, integrity } = src; + script.src = url; + if (integrity) { + script.integrity = integrity; + script.crossOrigin = 'anonymous'; + } + } else { + script.src = src; + } + (parentNode || document.head).appendChild(script); + } + }); + }, + + loadComments: function(selector, legacyCallback) { + if (legacyCallback) { + return this.loadComments(selector).then(legacyCallback); + } + return new Promise(resolve => { + const element = document.querySelector(selector); + if (!CONFIG.comments.lazyload || !element) { + resolve(); + return; + } + const intersectionObserver = new IntersectionObserver((entries, observer) => { + const entry = entries[0]; + if (!entry.isIntersecting) return; + + resolve(); + observer.disconnect(); + }); + intersectionObserver.observe(element); + }); + } +}; diff --git a/exampleSite/config.yaml b/exampleSite/config.yaml new file mode 100644 index 0000000..6c64a95 --- /dev/null +++ b/exampleSite/config.yaml @@ -0,0 +1,907 @@ +# =============================================================== +# It's recommended to use Alternate Theme Config to configure NexT +# Modifying this file may result in merge conflict +# See: https://theme-next.js.org/docs/getting-started/configuration +# =============================================================== + +baseURL: / + +theme: hugo-theme-next + +params: + # --------------------------------------------------------------- + # Theme Core Configuration Settings + # See: https://theme-next.js.org/docs/theme-settings/ + # --------------------------------------------------------------- + + # Allow to cache content generation. + cache: + enable: true + + # Remove unnecessary files after hexo generate. + minify: false + + # Define custom file paths. + # Create your custom files in site directory `source/_data` and uncomment needed files below. + custom_file_path: + #head: source/_data/head.njk + #header: source/_data/header.njk + #sidebar: source/_data/sidebar.njk + #postMeta: source/_data/post-meta.njk + #postBodyEnd: source/_data/post-body-end.njk + #footer: source/_data/footer.njk + #bodyEnd: source/_data/body-end.njk + #variable: source/_data/variables.styl + #mixin: source/_data/mixins.styl + #style: source/_data/styles.styl + + + # --------------------------------------------------------------- + # Scheme Settings + # --------------------------------------------------------------- + + # Schemes + scheme: Muse + #scheme: Mist + #scheme: Pisces + #scheme: Gemini + + # Dark Mode + darkmode: false + + + # --------------------------------------------------------------- + # Site Information Settings + # --------------------------------------------------------------- + + favicon: + small: /images/favicon-16x16-next.png + medium: /images/favicon-32x32-next.png + apple_touch_icon: /images/apple-touch-icon-next.png + safari_pinned_tab: /images/logo.svg + #android_manifest: /manifest.json + + # Custom Logo (Warning: Do not support scheme Mist) + custom_logo: #/uploads/custom-logo.jpg + + # Creative Commons 4.0 International License. + # See: https://creativecommons.org/about/cclicenses/ + creative_commons: + # Available values: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | cc-zero + license: by-nc-sa + # Available values: big | small + size: small + sidebar: false + post: false + # You can set a language value if you prefer a translated version of CC license, e.g. deed.zh + # CC licenses are available in 39 languages, you can find the specific and correct abbreviation you need on https://creativecommons.org + language: + + # Open graph settings + # See: https://hexo.io/docs/helpers#open-graph + open_graph: + enable: true + options: + #twitter_card: + #twitter_id: + #twitter_site: + #twitter_image: + #google_plus: + #fb_admins: + #fb_app_id: + + + # --------------------------------------------------------------- + # Menu Settings + # --------------------------------------------------------------- + + # Usage: `Key: /link/ || icon` + # Key is the name of menu item. If the translation for this item is available, the translated text will be loaded, otherwise the Key name will be used. Key is case-sensitive. + # Value before `||` delimiter is the target link, value after `||` delimiter is the name of Font Awesome icon. + # External url should start with http:// or https:// + menu: + #home: / || fa fa-home + #about: /about/ || fa fa-user + #tags: /tags/ || fa fa-tags + #categories: /categories/ || fa fa-th + #archives: /archives/ || fa fa-archive + #schedule: /schedule/ || fa fa-calendar + #sitemap: /sitemap.xml || fa fa-sitemap + #commonweal: /404/ || fa fa-heartbeat + + # Enable / Disable menu icons / item badges. + menu_settings: + icons: true + badges: false + + + # --------------------------------------------------------------- + # Sidebar Settings + # See: https://theme-next.js.org/docs/theme-settings/sidebar + # --------------------------------------------------------------- + + sidebar: + # Sidebar Position. + position: left + #position: right + + # Manual define the sidebar width. If commented, will be default for: + # Muse | Mist: 320 + # Pisces | Gemini: 240 + #width: 300 + + # Sidebar Display (only for Muse | Mist), available values: + # - post expand on posts automatically. Default. + # - always expand for all pages automatically. + # - hide expand only when click on the sidebar toggle icon. + # - remove totally remove sidebar including sidebar toggle. + display: post + + # Sidebar padding in pixels. + padding: 18 + # Sidebar offset from top menubar in pixels (only for Pisces | Gemini). + offset: 12 + + # Sidebar Avatar + avatar: + # Replace the default image and set the url here. + url: #/images/avatar.gif + # If true, the avatar will be displayed in circle. + rounded: false + # If true, the avatar will be rotated with the cursor. + rotated: false + + # Posts / Categories / Tags in sidebar. + site_state: true + + # Social Links + # Usage: `Key: permalink || icon` + # Key is the link label showing to end users. + # Value before `||` delimiter is the target permalink, value after `||` delimiter is the name of Font Awesome icon. + social: + #GitHub: https://github.com/yourname || fab fa-github + #E-Mail: mailto:yourname@gmail.com || fa fa-envelope + #Weibo: https://weibo.com/yourname || fab fa-weibo + #Google: https://plus.google.com/yourname || fab fa-google + #Twitter: https://twitter.com/yourname || fab fa-twitter + #FB Page: https://www.facebook.com/yourname || fab fa-facebook + #StackOverflow: https://stackoverflow.com/yourname || fab fa-stack-overflow + #YouTube: https://youtube.com/yourname || fab fa-youtube + #Instagram: https://instagram.com/yourname || fab fa-instagram + #Skype: skype:yourname?call|chat || fab fa-skype + + social_icons: + enable: true + icons_only: false + transition: false + + # Blog rolls + links_settings: + icon: fa fa-globe + title: Links + # Available values: block | inline + layout: block + + links: + #Title: https://example.com + + # Table of Contents in the Sidebar + # Front-matter variable (nonsupport wrap expand_all). + toc: + enable: true + # Automatically add list number to toc. + number: true + # If true, all words will placed on next lines if header width longer then sidebar width. + wrap: false + # If true, all level of TOC in a post will be displayed, rather than the activated part of it. + expand_all: false + # Maximum heading depth of generated toc. + max_depth: 6 + + + # --------------------------------------------------------------- + # Footer Settings + # See: https://theme-next.js.org/docs/theme-settings/footer + # --------------------------------------------------------------- + + # Show multilingual switcher in footer. + language_switcher: false + + footer: + # Specify the year when the site was setup. If not defined, current year will be used. + #since: 2021 + + # Icon between year and copyright info. + icon: + # Icon name in Font Awesome. See: https://fontawesome.com/icons + name: fa fa-heart + # If you want to animate the icon, set it to true. + animated: false + # Change the color of icon, using Hex Code. + color: "#ff0000" + + # If not defined, `author` from Hexo `_config.yml` will be used. + copyright: + + # Powered by Hexo & NexT + powered: true + + # Beian ICP and gongan information for Chinese users. See: https://beian.miit.gov.cn, http://www.beian.gov.cn + beian: + enable: false + icp: + # The digit in the num of gongan beian. + gongan_id: + # The full num of gongan beian. + gongan_num: + # The icon for gongan beian. See: http://www.beian.gov.cn/portal/download + gongan_icon_url: + + + # --------------------------------------------------------------- + # Post Settings + # See: https://theme-next.js.org/docs/theme-settings/posts + # --------------------------------------------------------------- + + # Automatically excerpt description in homepage as preamble text. + excerpt_description: true + + # Read more button + # If true, the read more button will be displayed in excerpt section. + read_more_btn: true + + # Post meta display settings + post_meta: + item_text: true + created_at: true + updated_at: + enable: true + another_day: true + categories: true + + # Post wordcount display settings + # Dependencies: https://github.com/next-theme/hexo-word-counter + symbols_count_time: + separated_meta: true + item_text_total: false + + # Use icon instead of the symbol # to indicate the tag at the bottom of the post + tag_icon: false + + # Donate (Sponsor) settings + # Front-matter variable (nonsupport animation). + reward_settings: + # If true, a donate button will be displayed in every article by default. + enable: false + animation: false + #comment: Buy me a coffee + + reward: + #wechatpay: /images/wechatpay.png + #alipay: /images/alipay.png + #paypal: /images/paypal.png + #bitcoin: /images/bitcoin.png + + # Subscribe through Telegram Channel, Twitter, etc. + # Usage: `Key: permalink || icon` (Font Awesome) + follow_me: + #Twitter: https://twitter.com/username || fab fa-twitter + #Telegram: https://t.me/channel_name || fab fa-telegram + #WeChat: /images/wechat_channel.jpg || fab fa-weixin + #RSS: /atom.xml || fa fa-rss + + # Related popular posts + # Dependencies: https://github.com/sergeyzwezdin/hexo-related-posts + related_posts: + enable: false + title: # Custom header, leave empty to use the default one + display_in_home: false + + # Post edit + # Easily browse and edit blog source code online. + post_edit: + enable: false + url: https://github.com/user-name/repo-name/tree/branch-name/subdirectory-name/ # Link for view source + #url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/ # Link for fork & edit + + # Show previous post and next post in post footer if exists + # Available values: left | right | false + post_navigation: left + + + # --------------------------------------------------------------- + # Custom Page Settings + # See: https://theme-next.js.org/docs/theme-settings/custom-pages + # --------------------------------------------------------------- + + # TagCloud settings for tags page. + tagcloud: + min: 12 # Minimum font size in px + max: 30 # Maximum font size in px + amount: 200 # Total amount of tags + orderby: name # Order of tags + order: 1 # Sort order + + # Google Calendar + # Share your recent schedule to others via calendar page. + calendar: + calendar_id: # Your Google account E-Mail + api_key: + orderBy: startTime + showLocation: false + offsetMax: 72 # Time Range + offsetMin: 4 # Time Range + showDeleted: false + singleEvents: true + maxResults: 250 + + + # --------------------------------------------------------------- + # Misc Theme Settings + # See: https://theme-next.js.org/docs/theme-settings/miscellaneous + # --------------------------------------------------------------- + + # Preconnect CDN for fonts and plugins. + # For more information: https://www.w3.org/TR/resource-hints/#preconnect + preconnect: false + + # Set the text alignment in posts / pages. + text_align: + # Available values: start | end | left | right | center | justify | justify-all | match-parent + desktop: justify + mobile: justify + + # Reduce padding / margin indents on devices with narrow width. + mobile_layout_economy: false + + # Browser header panel color. + theme_color: + light: "#222" + dark: "#222" + + # Override browsers' default behavior. + body_scrollbar: + # Place the scrollbar over the content. + overlay: false + # Present the scrollbar even if the content is not overflowing. + stable: false + + codeblock: + # Code Highlight theme + # All available themes: https://theme-next.js.org/highlight/ + theme: + light: default + dark: stackoverflow-dark + prism: + light: prism + dark: prism-dark + # Add copy button on codeblock + copy_button: + enable: false + # Available values: default | flat | mac + style: + + back2top: + enable: true + # Back to top in sidebar. + sidebar: false + # Scroll percent label in b2t button. + scrollpercent: false + + # Reading progress bar + reading_progress: + enable: false + # Available values: left | right + start_at: left + # Available values: top | bottom + position: top + reversed: false + color: "#37c6c0" + height: 3px + + # Bookmark Support + bookmark: + enable: false + # Customize the color of the bookmark. + color: "#222" + # If auto, save the reading progress when closing the page or clicking the bookmark-icon. + # If manual, only save it by clicking the bookmark-icon. + save: auto + + # `Follow me on GitHub` banner in the top-right corner. + github_banner: + enable: false + permalink: https://github.com/yourname + title: Follow me on GitHub + + + # --------------------------------------------------------------- + # Font Settings + # --------------------------------------------------------------- + # Find fonts on Google Fonts (https://fonts.google.com) + # All fonts set here will have the following styles: + # light | light italic | normal | normal italic | bold | bold italic + # Be aware that setting too much fonts will cause site running slowly + # --------------------------------------------------------------- + # Web Safe fonts are recommended for `global` (and `title`): + # Arial | Tahoma | Helvetica | Times New Roman | Courier New | Verdana | Georgia | Palatino | Garamond | Comic Sans MS | Trebuchet MS + # --------------------------------------------------------------- + + font: + enable: false + + # Uri of fonts host, e.g. https://fonts.googleapis.com (Default). + host: + + # Font options: + # `external: true` will load this font family from `host` above. + # `family: Times New Roman`. Without any quotes. + # `size: x.x`. Use `em` as unit. Default: 1 (16px) + + # Global font settings used for all elements inside . + global: + external: true + family: Lato + size: + + # Font settings for site title (.site-title). + title: + external: true + family: + size: + + # Font settings for headlines (

to

). + headings: + external: true + family: + size: + + # Font settings for posts (.post-body). + posts: + external: true + family: + + # Font settings for and code blocks. + codes: + external: true + family: + + + # --------------------------------------------------------------- + # SEO Settings + # See: https://theme-next.js.org/docs/theme-settings/seo + # --------------------------------------------------------------- + + # If true, site-subtitle will be added to index page. + # Remember to set up your site-subtitle in Hexo `_config.yml` (e.g. subtitle: Subtitle) + index_with_subtitle: false + + # Automatically add external URL with Base64 encrypt & decrypt. + exturl: false + # If true, an icon will be attached to each external URL + exturl_icon: true + + # Google Webmaster tools verification. + # See: https://developers.google.com/search + google_site_verification: + + # Bing Webmaster tools verification. + # See: https://www.bing.com/webmasters + bing_site_verification: + + # Yandex Webmaster tools verification. + # See: https://webmaster.yandex.ru + yandex_site_verification: + + # Baidu Webmaster tools verification. + # See: https://ziyuan.baidu.com/site + baidu_site_verification: + + + # --------------------------------------------------------------- + # Third Party Plugins & Services Settings + # See: https://theme-next.js.org/docs/third-party-services/ + # More plugins: https://github.com/next-theme/awesome-next + # You may need to install the corresponding dependency packages + # --------------------------------------------------------------- + + # Math Formulas Render Support + # Warning: Please install / uninstall the relevant renderer according to the documentation. + # See: https://theme-next.js.org/docs/third-party-services/math-equations + # Server-side plugin: https://github.com/next-theme/hexo-filter-mathjax + math: + # Default (false) will load mathjax / katex script on demand. + # That is it only render those page which has `mathjax: true` in front-matter. + # If you set it to true, it will load mathjax / katex script EVERY PAGE. + every_page: false + + mathjax: + enable: false + # Available values: none | ams | all + tags: none + + katex: + enable: false + # See: https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex + copy_tex: false + + # Easily enable fast Ajax navigation on your website. + # For more information: https://github.com/next-theme/pjax + pjax: false + + # FancyBox is a tool that offers a nice and elegant way to add zooming functionality for images. + # For more information: https://fancyapps.com/fancybox/ + fancybox: false + + # A JavaScript library for zooming images like Medium. + # Warning: Do not enable both `fancybox` and `mediumzoom`. + # For more information: https://medium-zoom.francoischalifour.com + mediumzoom: false + + # Vanilla JavaScript plugin for lazyloading images. + # For more information: https://apoorv.pro/lozad.js/demo/ + lazyload: false + + # Pangu Support + # For more information: https://github.com/vinta/pangu.js + # Server-side plugin: https://github.com/next-theme/hexo-pangu + pangu: false + + # Quicklink Support + # For more information: https://getquick.link + # Front-matter variable (nonsupport home archive). + quicklink: + enable: false + + # Home page and archive page can be controlled through home and archive options below. + # This configuration item is independent of `enable`. + home: false + archive: false + + # Default (true) will initialize quicklink after the load event fires. + delay: true + # Custom a time in milliseconds by which the browser must execute prefetching. + timeout: 3000 + # Default (true) will attempt to use the fetch() API if supported (rather than link[rel=prefetch]). + priority: true + + + # --------------------------------------------------------------- + # Comments Settings + # See: https://theme-next.js.org/docs/third-party-services/comments + # --------------------------------------------------------------- + + # Multiple Comment System Support + comments: + # Available values: tabs | buttons + style: tabs + # Choose a comment system to be displayed by default. + # Available values: disqus | disqusjs | changyan | livere | gitalk | utterances + active: + # Setting `true` means remembering the comment system selected by the visitor. + storage: true + # Lazyload all comment systems. + lazyload: false + # Modify texts or order for any naves, here are some examples. + nav: + #disqus: + # text: Load Disqus + # order: -1 + #gitalk: + # order: -2 + + # Disqus + # For more information: https://disqus.com + disqus: + enable: false + shortname: + count: true + + # DisqusJS + # For more information: https://disqusjs.skk.moe + disqusjs: + enable: false + # API Endpoint of Disqus API (https://disqus.com/api/docs/). + # Leave api empty if you are able to connect to Disqus API. Otherwise you need a reverse proxy for it. + # For example: + # api: https://disqus.skk.moe/disqus/ + api: + apikey: # Register new application from https://disqus.com/api/applications/ + shortname: # See: https://disqus.com/admin/settings/general/ + + # Changyan + # For more information: https://changyan.kuaizhan.com + changyan: + enable: false + appid: + appkey: + + # LiveRe comments system + # You can get your uid from https://livere.com/insight/myCode (General web site) + livere_uid: # + + # Gitalk + # For more information: https://gitalk.github.io + gitalk: + enable: false + github_id: # GitHub repo owner + repo: # Repository name to store issues + client_id: # GitHub Application Client ID + client_secret: # GitHub Application Client Secret + admin_user: # GitHub repo owner and collaborators, only these guys can initialize gitHub issues + distraction_free_mode: true # Facebook-like distraction free mode + # When the official proxy is not available, you can change it to your own proxy address + proxy: https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token # This is official proxy address + # Gitalk's display language depends on user's browser or system environment + # If you want everyone visiting your site to see a uniform language, you can set a force language value + # Available values: en | es-ES | fr | ru | zh-CN | zh-TW + language: + + # Utterances + # For more information: https://utteranc.es + utterances: + enable: false + repo: user-name/repo-name # Github repository owner and name + # Available values: pathname | url | title | og:title + issue_term: pathname + # Available values: github-light | github-dark | preferred-color-scheme | github-dark-orange | icy-dark | dark-blue | photon-dark | boxy-light + theme: github-light + + # Isso + # For more information: https://posativ.org/isso/ + isso: # + + + # --------------------------------------------------------------- + # Post Widgets & Content Sharing Services + # See: https://theme-next.js.org/docs/third-party-services/post-widgets + # --------------------------------------------------------------- + + # Star rating support to each article. + # To get your ID visit https://widgetpack.com + rating: + enable: false + id: # + color: "#fc6423" + + # AddThis Share. See: https://www.addthis.com + # Go to https://www.addthis.com/dashboard to customize your tools. + add_this_id: + + + # --------------------------------------------------------------- + # Statistics and Analytics + # See: https://theme-next.js.org/docs/third-party-services/statistics-and-analytics + # --------------------------------------------------------------- + + # Google Analytics + # See: https://analytics.google.com + google_analytics: + tracking_id: # + # By default, NexT will load an external gtag.js script on your site. + # If you only need the pageview feature, set the following option to true to get a better performance. + only_pageview: false + + # Baidu Analytics + # See: https://tongji.baidu.com + baidu_analytics: # + + # Growingio Analytics + # See: https://www.growingio.com + growingio_analytics: # + + # Cloudflare Web Analytics + # See: https://www.cloudflare.com/web-analytics/ + cloudflare_analytics: + + # Microsoft Clarity Analytics + # See: https://clarity.microsoft.com/ + clarity_analytics: # + + # Show number of visitors of each article. + # You can visit https://www.leancloud.cn to get AppID and AppKey. + leancloud_visitors: + enable: false + app_id: # + app_key: # + # Required for apps from CN region + server_url: # + # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security + # If you don't care about security in leancloud counter and just want to use it directly + # (without hexo-leancloud-counter-security plugin), set `security` to `false`. + security: true + + # Another tool to show number of visitors to each article. + # Visit https://console.firebase.google.com/u/0/ to get apiKey and projectId. + # Visit https://firebase.google.com/docs/firestore/ to get more information about firestore. + firestore: + enable: false + collection: articles # Required, a string collection name to access firestore database + apiKey: # Required + projectId: # Required + + # Show Views / Visitors of the website / page with busuanzi. + # For more information: http://ibruce.info/2015/04/04/busuanzi/ + busuanzi_count: + enable: false + total_visitors: true + total_visitors_icon: fa fa-user + total_views: true + total_views_icon: fa fa-eye + post_views: true + post_views_icon: far fa-eye + + + # --------------------------------------------------------------- + # Search Services + # See: https://theme-next.js.org/docs/third-party-services/search-services + # --------------------------------------------------------------- + + # Algolia Search + # For more information: https://www.algolia.com + algolia_search: + enable: false + hits: + per_page: 10 + + # Local Search + # Dependencies: https://github.com/next-theme/hexo-generator-searchdb + local_search: + enable: false + # If auto, trigger search by changing input. + # If manual, trigger search by pressing enter key or search button. + trigger: auto + # Show top n results per article, show all results by setting to -1 + top_n_per_article: 1 + # Unescape html strings to the readable one. + unescape: false + # Preload the search data when the page loads. + preload: false + + + # --------------------------------------------------------------- + # Chat Services + # See: https://theme-next.js.org/docs/third-party-services/chat-services + # --------------------------------------------------------------- + + # A button to open designated chat widget in sidebar. + # Firstly, you need to enable and configure the chat service. + chat: + enable: false + icon: fa fa-comment # Icon name in Font Awesome, set false to disable icon. + text: Chat # Button text, change it as you wish. + + # Chatra Support + # For more information: https://chatra.com + # Dashboard: https://app.chatra.io/settings/general + chatra: + enable: false + async: true + id: # Visit Dashboard to get your ChatraID + #embed: # Unfinished experimental feature for developers. See: https://chatra.com/help/api/#injectto + + # Tidio Support + # For more information: https://www.tidio.com + # Dashboard: https://www.tidio.com/panel/dashboard + tidio: + enable: false + key: # Public Key, get it from dashboard. See: https://www.tidio.com/panel/settings/developer + + # Gitter Support + # For more information: https://gitter.im + gitter: + enable: false + room: + + + # --------------------------------------------------------------- + # Tags Settings + # See: https://theme-next.js.org/docs/tag-plugins/ + # --------------------------------------------------------------- + + # Note tag (bootstrap callout) + note: + # Note tag style values: + # - simple bootstrap callout old alert style. Default. + # - modern bootstrap callout new (v2-v3) alert style. + # - flat flat callout style with background, like on Mozilla or StackOverflow. + # - disabled disable all CSS styles import of note tag. + style: simple + icons: false + # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6). + # Offset also applied to label tag variables. This option can work with disabled note tag. + light_bg_offset: 0 + + # Tabs tag + tabs: + # Make the nav bar of tabs with long content stick to the top. + sticky: false + transition: + tabs: false + labels: true + + # PDF tag + # NexT will try to load pdf files natively, if failed, pdf.js will be used. + # So, you have to install the dependency of pdf.js if you want to use pdf tag and make it available to all browsers. + # Dependencies: https://github.com/next-theme/theme-next-pdf + pdf: + enable: false + # Default height + height: 500px + + # Mermaid tag + mermaid: + enable: false + # Available themes: default | dark | forest | neutral + theme: + light: default + dark: dark + + + # --------------------------------------------------------------- + # Animation Settings + # --------------------------------------------------------------- + + # Use Animate.css to animate everything. + # For more information: https://animate.style + motion: + enable: true + async: false + transition: + # All available transition variants: https://theme-next.js.org/animate/ + post_block: fadeIn + post_header: fadeInDown + post_body: fadeInDown + coll_header: fadeInLeft + # Only for Pisces | Gemini. + sidebar: fadeInUp + + # Progress bar in the top during page loading. + # For more information: https://github.com/CodeByZach/pace + pace: + enable: false + # All available colors: + # black | blue | green | orange | pink | purple | red | silver | white | yellow + color: blue + # All available themes: + # big-counter | bounce | barber-shop | center-atom | center-circle | center-radar | center-simple + # corner-indicator | fill-left | flat-top | flash | loading-bar | mac-osx | material | minimal + theme: minimal + + # Canvas ribbon + # For more information: https://github.com/hustcc/ribbon.js + canvas_ribbon: + enable: false + size: 300 # The width of the ribbon + alpha: 0.6 # The transparency of the ribbon + zIndex: -1 # The display level of the ribbon + + + # --------------------------------------------------------------- + # CDN Settings + # See: https://theme-next.js.org/docs/advanced-settings/vendors + # --------------------------------------------------------------- + + vendors: + # The CDN provider of NexT internal scripts. + # Available values: local | jsdelivr | unpkg | cdnjs | custom + # Warning: If you are using the latest master branch of NexT, please set `internal: local` + internal: local + # The default CDN provider of third-party plugins. + # Available values: local | jsdelivr | unpkg | cdnjs | custom + # Dependencies for `plugins: local`: https://github.com/next-theme/plugins + plugins: jsdelivr + # Custom CDN URL + # For example: + # custom_cdn_url: https://cdn.jsdelivr.net/npm/${npm_name}@${version}/${minified} + # custom_cdn_url: https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${cdnjs_file} + custom_cdn_url: + + # Assets + # Accelerate delivery of static files using a CDN + # The js option is only valid when vendors.internal is local. + css: css + js: js + images: images + + diff --git a/exampleSite/content/hello-world.md b/exampleSite/content/hello-world.md new file mode 100644 index 0000000..a34ef48 --- /dev/null +++ b/exampleSite/content/hello-world.md @@ -0,0 +1,59 @@ +--- +title: 'Hugo blog Hello World' +description: 'Short description of the article.' +keywords: 'Key words' +isCJKLanguage: true + +author: 'Author of the article' +lastmod: '2022-05-21T17:06:24+08:00' +publishDate: '2022-05-21T17:06:24+08:00' +weight: 1 + +categories: + - +tags: + - + - + +toc: false +draft: true +url: 'hello_world.html' +--- + +[Hugo](https://gohugo.io/) is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. + +## Quick Start + +### Create a new post + +```shell +$ hugo new hello-world.md +``` + +More info: [Content's Formats](https://gohugo.io/content-management/formats/) + +### Run server + +```shell +$ hugo server +``` + +More info: [Hugo Server CLI](https://gohugo.io/commands/hugo_server/) + +### Generate static files + +```shell +$ hugo +``` + +More info: [Hugo Build Site](https://gohugo.io/commands/hugo/) + +### Deploy to remote sites + +```language +$ hugo deploy +``` + +More info: [Hugo Deployment](https://gohugo.io/commands/hugo_deploy/) + +See you will enjoy the Hugo journey and good luck for you! \ No newline at end of file diff --git a/i18n/en-us.toml b/i18n/en-us.toml new file mode 100644 index 0000000..a162721 --- /dev/null +++ b/i18n/en-us.toml @@ -0,0 +1,49 @@ +#-------------------------------------- +# English Version +#-------------------------------------- + +[ColoneFlag] + other = ":" + +[SitePostsTitle] + other = "Posts" +[SiteCatesTitle] + other = "Categories" +[SiteTagsTitle] + other = "Tags" +[TableOfContents] + other = "TOC" +[SiteInfo] + other = "Site Info" +[RSSTitle] + other = "RSS Subscribe" +[CCLinkTitle] + other = "Creative Commons" + +[PostPublishDate] + other = "Publish" +[PostPublishTime] + other = "Create Time" +[PostLastModDate] + other = "Update" +[PostLastModTime] + other = "Modify Time" +[PostWords] + other = "Words" +[PostWordCount] + other = "{{- .WordCount -}}" +[PostReading] + other = "Read" +[PostReadTime] + other = "{{- .ReadingTime -}}min" +[PostVisitor] + other = "Views" +[PostCatg] + other = "Categories" +[PostTag] + other = "Tags" +[PostReadMore] + other = "Read More" + +[FooterPowerby] + other = "Power by %s" \ No newline at end of file diff --git a/i18n/zh-cn.toml b/i18n/zh-cn.toml new file mode 100644 index 0000000..63d0942 --- /dev/null +++ b/i18n/zh-cn.toml @@ -0,0 +1,49 @@ +#-------------------------------------- +# 中文版本 +#-------------------------------------- + +[ColoneFlag] + other = ":" + +[SitePostsTitle] + other = "日志" +[SiteCatesTitle] + other = "分类" +[SiteTagsTitle] + other = "标签" +[TableOfContents] + other = "文章目录" +[SiteInfo] + other = "站点概览" +[RSSTitle] + other = "RSS 订阅" +[CCLinkTitle] + other = "共享知识" + +[PostPublishDate] + other = "发表于" +[PostPublishTime] + other = "创建时间" +[PostLastModDate] + other = "更新于" +[PostLastModTime] + other = "修改时间" +[PostWords] + other = "字数" +[PostWordCount] + other = "{{- .WordCount -}}" +[PostReading] + other = "阅读" +[PostReadTime] + other = "{{- .ReadingTime -}}分钟" +[PostVisitor] + other = "浏览数" +[PostCatg] + other = "分类" +[PostTag] + other = "标签" +[PostReadMore] + other = "阅读全文" + +[FooterPowerby] + other = "由 %s 强力驱动" \ No newline at end of file diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..5f8e2ec --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,11 @@ + + + {{- partial "head.html" . -}} + + {{- partial "header.html" . -}} +
+ {{- block "main" . }}{{- end }} +
+ {{- partial "footer.html" . -}} + + diff --git a/layouts/_default/list.html b/layouts/_default/list.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/_default/single.html b/layouts/_default/single.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..02ce795 --- /dev/null +++ b/layouts/index.html @@ -0,0 +1,2 @@ +{{- define "main" }} +{{- end }} \ No newline at end of file diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/partials/head.html b/layouts/partials/head.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/partials/header.html b/layouts/partials/header.html new file mode 100644 index 0000000..e69de29 diff --git a/static/css/hover.css b/static/css/hover.css new file mode 100644 index 0000000..76df7fb --- /dev/null +++ b/static/css/hover.css @@ -0,0 +1,176 @@ +/** Animation for link hover style */ + +@keyframes wobble-vertical { + 16.65% { + transform: translateX(8px); + } + + 33.3% { + transform: translateX(-6px); + } + + 49.95% { + transform: translateX(4px); + } + + 66.6% { + transform: translateX(-2px); + } + + 83.25% { + transform: translateX(1px); + } + + 100% { + transform: translateX(0); + } +} + +/* Icon Pulse */ +@-webkit-keyframes hvr-icon-pulse { + 25% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + 75% { + -webkit-transform: scale(0.8); + transform: scale(0.8); + } +} +@keyframes hvr-icon-pulse { + 25% { + -webkit-transform: scale(1.3); + transform: scale(1.3); + } + 75% { + -webkit-transform: scale(0.8); + transform: scale(0.8); + } +} +.hvr-icon-pulse { + display: inline-block; + vertical-align: middle; + -webkit-transform: perspective(1px) translateZ(0); + transform: perspective(1px) translateZ(0); + box-shadow: 0 0 1px rgba(0, 0, 0, 0); +} +.hvr-icon-pulse .hvr-icon { + -webkit-transform: translateZ(0); + transform: translateZ(0); + -webkit-transition-timing-function: ease-out; + transition-timing-function: ease-out; +} +.hvr-icon-pulse:hover .hvr-icon, .hvr-icon-pulse:focus .hvr-icon, .hvr-icon-pulse:active .hvr-icon { + -webkit-animation-name: hvr-icon-pulse; + animation-name: hvr-icon-pulse; + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-timing-function: linear; + animation-timing-function: linear; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +/* Bounce To Right */ +.hvr-bounce-to-right { + background: var(--btn-default-bg); + border: 2px solid var(--btn-default-border-color); + border-radius: 2px; + color: var(--btn-default-color); + display: inline-block; + font-size: 0.875em; + line-height: 2; + padding: 0 20px; + display: inline-block; + vertical-align: middle; + -webkit-transform: perspective(1px) translateZ(0); + transform: perspective(1px) translateZ(0); + box-shadow: 0 0 1px rgba(0, 0, 0, 0); + position: relative; + -webkit-transition-property: color; + transition-property: color; + -webkit-transition-duration: 0.5s; + transition-duration: 0.5s; +} +.hvr-bounce-to-right:before { + content: ""; + position: absolute; + z-index: -1; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--btn-default-hover-bg); + -webkit-transform: scaleX(0); + transform: scaleX(0); + -webkit-transform-origin: 0 50%; + transform-origin: 0 50%; + -webkit-transition-property: transform; + transition-property: transform; + -webkit-transition-duration: 0.5s; + transition-duration: 0.5s; + -webkit-transition-timing-function: ease-out; + transition-timing-function: ease-out; +} +.hvr-bounce-to-right:hover, .hvr-bounce-to-right:focus, .hvr-bounce-to-right:active { + background: var(--btn-default-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); +} +.hvr-bounce-to-right:hover:before, .hvr-bounce-to-right:focus:before, .hvr-bounce-to-right:active:before { + -webkit-transform: scaleX(1); + transform: scaleX(1); + -webkit-transition-timing-function: cubic-bezier(0.52, 1.64, 0.37, 0.66); + transition-timing-function: cubic-bezier(0.52, 1.64, 0.37, 0.66); +} + +/* Shutter Out Horizontal */ +.hvr-shutter-out-horizontal { + background: var(--btn-default-bg); + border: 2px solid var(--btn-default-border-color); + border-radius: 2px; + color: var(--btn-default-color); + display: inline-block; + font-size: 0.875em; + line-height: 2; + padding: 0 20px; + display: inline-block; + vertical-align: middle; + -webkit-transform: perspective(1px) translateZ(0); + transform: perspective(1px) translateZ(0); + box-shadow: 0 0 1px rgba(0, 0, 0, 0); + position: relative; + -webkit-transition-property: color; + transition-property: color; + -webkit-transition-duration: 0.3s; + transition-duration: 0.3s; +} +.hvr-shutter-out-horizontal:before { + content: ""; + position: absolute; + z-index: -1; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: var(--btn-default-hover-bg); + -webkit-transform: scaleX(0); + transform: scaleX(0); + -webkit-transform-origin: 50%; + transform-origin: 50%; + -webkit-transition-property: transform; + transition-property: transform; + -webkit-transition-duration: 0.3s; + transition-duration: 0.3s; + -webkit-transition-timing-function: ease-out; + transition-timing-function: ease-out; +} +.hvr-shutter-out-horizontal:hover, .hvr-shutter-out-horizontal:focus, .hvr-shutter-out-horizontal:active { + background: var(--btn-default-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); +} +.hvr-shutter-out-horizontal:hover:before, .hvr-shutter-out-horizontal:focus:before, .hvr-shutter-out-horizontal:active:before { + -webkit-transform: scaleX(1); + transform: scaleX(1); +} \ No newline at end of file diff --git a/static/imgs/cc/big/by.svg b/static/imgs/cc/big/by.svg new file mode 100644 index 0000000..0bcb700 --- /dev/null +++ b/static/imgs/cc/big/by.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/big/by_nc.svg b/static/imgs/cc/big/by_nc.svg new file mode 100644 index 0000000..048cb50 --- /dev/null +++ b/static/imgs/cc/big/by_nc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/big/by_nc_nd.svg b/static/imgs/cc/big/by_nc_nd.svg new file mode 100644 index 0000000..7d8dca7 --- /dev/null +++ b/static/imgs/cc/big/by_nc_nd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/big/by_nc_sa.svg b/static/imgs/cc/big/by_nc_sa.svg new file mode 100644 index 0000000..eccc951 --- /dev/null +++ b/static/imgs/cc/big/by_nc_sa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/big/by_nd.svg b/static/imgs/cc/big/by_nd.svg new file mode 100644 index 0000000..6e222aa --- /dev/null +++ b/static/imgs/cc/big/by_nd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/big/by_sa.svg b/static/imgs/cc/big/by_sa.svg new file mode 100644 index 0000000..c763ea3 --- /dev/null +++ b/static/imgs/cc/big/by_sa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/big/cc_zero.svg b/static/imgs/cc/big/cc_zero.svg new file mode 100644 index 0000000..75421af --- /dev/null +++ b/static/imgs/cc/big/cc_zero.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/cc.svg b/static/imgs/cc/cc.svg new file mode 100644 index 0000000..f4b2243 --- /dev/null +++ b/static/imgs/cc/cc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/by.svg b/static/imgs/cc/small/by.svg new file mode 100644 index 0000000..e6232e7 --- /dev/null +++ b/static/imgs/cc/small/by.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/by_nc.svg b/static/imgs/cc/small/by_nc.svg new file mode 100644 index 0000000..5ed67ad --- /dev/null +++ b/static/imgs/cc/small/by_nc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/by_nc_nd.svg b/static/imgs/cc/small/by_nc_nd.svg new file mode 100644 index 0000000..6df1c9f --- /dev/null +++ b/static/imgs/cc/small/by_nc_nd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/by_nc_sa.svg b/static/imgs/cc/small/by_nc_sa.svg new file mode 100644 index 0000000..88a4641 --- /dev/null +++ b/static/imgs/cc/small/by_nc_sa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/by_nd.svg b/static/imgs/cc/small/by_nd.svg new file mode 100644 index 0000000..3db35c3 --- /dev/null +++ b/static/imgs/cc/small/by_nd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/by_sa.svg b/static/imgs/cc/small/by_sa.svg new file mode 100644 index 0000000..2513f02 --- /dev/null +++ b/static/imgs/cc/small/by_sa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/cc/small/cc_zero.svg b/static/imgs/cc/small/cc_zero.svg new file mode 100644 index 0000000..cf62fdb --- /dev/null +++ b/static/imgs/cc/small/cc_zero.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/imgs/gongan.png b/static/imgs/gongan.png new file mode 100644 index 0000000000000000000000000000000000000000..1328a00b33a63ab2cf63d31a25d9ec9c03345e97 GIT binary patch literal 869 zcmV-r1DgDaP)Px$o={9wMNDaN?dh_>npMxSiQdbY>D-6ax^C>_x%TtU z$DUcemQvTeY{#EB;nJDbxhLh-jP>lb;@EiK)S&zIyX)qv-N~8ErEB2Ps>7FL#hy{b zpK#pAfzPyrzMECaq-e^nh26@J&97grnR3j&gVeum!Lfzj%zslvQaLYDvZ-g;z+L6q zkKxaMu9qj_(Q9d1Tg<+ebZBg&mw$|YXV?{XA`{D_D$%Vx$e$z5uxP;%4#ofg z0RdUtx+>138p)+h(5WEQu^HI5MbWP^003PR3qvRTjMW=Pgq z8@*&G(x5oJpCj48J)MFyG%H2OJ}AdAALGO&Nkmf2r(xK_Xs?wf)V4A<97K-*9N^Pz z7y?eK2@=nDEzf=?B^pGyrAl*dNaEph002zhfgLIUMAR`4U0X=ff<4}Q98Co`#IHIX z08TG5RA5g#)08~UmqE6pRL!Cy%Ar#vLITtP001;}QchC<4~QY0UA`9v{lfgpZ2X5W zmwFvfdgCb7tXsIcrQBDO_PCOPqCp~=(v{rPqjJ#+t{URv(B_*N6n-mNUCB~m7!Tb_Vn0tUS|^P&J|kGGP~69hp% zzC5e~0@;k2&nQW@ng`@tk=j&>dvwG1Udo-{zw+6DuWAy=-2QTNV4++nSL#%Q*$`-} zU8g?a($#hDx$EX)YXTW+PA_zpPA1crPrfSMFVH$mrzi-@oL)d~j%G!&glkMZ?oS;j zA`#4miv-Nfo;X3)2u5Re7N3yL?^EF+1PLMx7CamomSkL~J961E1Vh8PMkTcjQyNDI vW$Z!Jp&1$kq`wu@@=2{;uN{?-DTMJ4Ys)^y6~RNg00000NkvXXu0mjf<(`qV literal 0 HcmV?d00001 diff --git a/static/imgs/hugo_next_avatar.png b/static/imgs/hugo_next_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..b5c94d433049ed6470e0d4a8a78be708b5c27d17 GIT binary patch literal 1120 zcmZWndrXse6urNGeGN+2Iv8{TY&9EmXepgT9)p!qhDd=95W6Kvd}3i*rEV3m z;*U{O`@blh(Yw0eIQ%sC$C~khy|O<_UbS2qRBMhCOE$^>u+lxbT68J<@27F41A|B3 zEE)`SIFD>!3YIZgqA$={ArB|Frq?ifNLEb8wO=>k#J2b%^cW$iW?45c7Siyf-lXg` zN!!-}5W`&2TV8&#`&q?~vHt3Njz&%O#N3&V9Xe6z43L#<`55})FT7eU1Vdy-q@WAgT3Jbwz;C3a8X1>P$ z2Q!xktkCqubbnGycO=olTcqo4k@HArt1L>NMG8jN7ONcQb6d}*&ti)Cz8Zoi^7(d3 zgMwgeePg$*0aeF1Bj+i^V`{sf$ln>3a{#{lka|Chwh0-f_k|WZ_en%!QUJ<`*Axpa zFA>bxV5%T*FV+LEPGQP}5bMA&q?dE#ySj8vdRU6Gt3Fa2C-)k)mP!C0rt zm$XC#v24Oi@CO>?fQBIKF|rzkmOz4!wfhmqlu&plE#1ofY}&i@vTpULc?E}kCKU~)ea zf|7t1jD9Jcu(J+=)|Wm8a~DLI;y8zeYHx%SE2T1uLd|JH+KJkHusg;(k(5!z5-FKv zfgPHTQp-rSJAEftx2}UJUlD|_+*K}ZQ;`Sv9kK&0p3=8^H4W_f)DvG^UkmGVP0bm2 zm)krYpih7eCSiNx6BO(XDG$Gi@qszgv-f?DMBwGxGQ{2W93oGgMZR@;<2w#l8MeC< M<5MI(V#T?C0SnZx7ytkO literal 0 HcmV?d00001 diff --git a/static/imgs/hugo_next_logo.png b/static/imgs/hugo_next_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9d30f3936ef20ac6340c2185cba52be11eb3ebc7 GIT binary patch literal 31634 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 Y`OS=Zk9`xr0GlEVp00i_>zopr0Ln3SJOBUy literal 0 HcmV?d00001 diff --git a/static/imgs/icons/apple_touch_icon_next.png b/static/imgs/icons/apple_touch_icon_next.png new file mode 100644 index 0000000000000000000000000000000000000000..ab587ceac614ba73323baf789c63f8fc4d87f7a3 GIT binary patch literal 1699 zcmV;U23+}xP)Px#Z%|BBMF0Q*6B85o`1sGy&;9-VgqEyGaVfr=jZ41 z^Yh)^-OJ0%MMXtTO-+@RmB7Hj2?+^pZEbsdd#I?WToxBW000HjNklJKB*^p~JvN#3L$A@cy*45!o#m5qgU3#C-QmhA5#U8-Z5) zQK4;w5ooh2n}N>mm$k9D{9X+}Kl_Z&MToyAMxfIfjzdEc z54s#UHAhdyZM{P(Yta2eJ$8;`zr_v3ZRH(dSBv_Lc)+3ln9+gsU>&B^w9>(Bcc8K3 zaoDjd2X;~1aVY+-FZpf!p;FV`EV-o1H2X?|qZCOnE_8@L)8%~3NNJqTjo1#4zMg}o z7jfB_G#i`!h|ripe@=`K96w%%P77#KSQ)XR^f=IA0W6gE1-kN2zmz6Let4B0tpm{$ zXyO_4s#Kcz2wmRf5j62NJ$T>4AEp02=vEa}v%uTm1eET9p2(s5h9c4AY8^U4*(IMY z>d0?epF@OBaufT|bLk}rKAv=_BlJZ(G}SYHyaQUUU&nZTMS9S2T(#J=-=-aCA~(`W z5C%rP<$SrPPiVIZ7e+o z%3|C-B>!MP!Jt_iS2~psw4wAMc$UembLJ$k!)s5?vy8vWD{rc7VGQd?5GuPoMv&hq-v z)U2~U>Kd9jp){irkNr_WTS*V1Ob-;T#j)6H*7nYbTF~_Rp?;J7J!^MHE|t>gmwz(7 zW^Gkz4QPa}7w#Zqkfnj*!b!AFPG zE~W=Ucgd_fN|G)@({sOM)|aavN*89$#|@8W?FMw+HRVCgI>uFxXf|(Sxl^o>p(V4X zQr}%vy3B-z(h=I=m@jo}o3)!tv%LgUVb;^k(e!94&A3Q8;ARfeGHa6kxqr!3ZjmJ4QWvlh_Cl~xpM+Db?0#(UOb)2w-VV6#=zdf}D!fym674ZTQtU&E}e z3<9c^w$CZe+9uU30W)ix>5?-|y zdX#2ePZd=2M>e3z3()kVI*Lh+d*txIw(*ExaV%CPNyl@#SeYf6by<>hUTJ35(xk@5 z4`?J$YLt`xUO+ErLTYB#K0p_YvRQkfv}D#{Y1SS<7d>ktCj0$Rx^328KtGtZD;1`} zMIJ?+EF{&?YvXE#sl%-Kv6w8+oyhbz_m% zyUJokp)pjhwwmv&r6cTPabsPcQfYYxnpjnOcx87iULriPX$HL5guUwRNt zXt`%?Txof`>PzWC&*qD=Bw5W8ynS7s4m30CCXovZuhiK0=CNpa*(N5hD=iJZ2sXG{ zjD2~OVy)>@N=s&K@Ic&+(x2`#YZK52&2#BX6_2k&%gcp~L0?bjlZf*zL#TW2R;;OX zF#|2__A&w8idFX53wka+s98@%TASDX`s1e++x5d{kUwl?9^L@`8g!TX!OH2~ z%&dPD#I3KW4U^P$=#Du02TcGPpaB}70UDqI+7|R?^u9-!FHFaN_#X%SZ~kFNXgml8 tr2!hC0UDqI8lV9hpaB}70UDs~$A7fJ(!6Rls%!uN002ovPDHLkV1nJVHP`?E literal 0 HcmV?d00001 diff --git a/static/imgs/icons/favicon.ico b/static/imgs/icons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8b14db36aaae2f37ed475476503904d943538127 GIT binary patch literal 4286 zcmd6pyGtWc6vl62jJiRHi7xme8k=oY&_V@^Wg82@Qc%&}7b+HlAX(Nz6rb3OBI=^x zpCFc27B=D=pClmoM4~31z2DIr#%$C{G$9kd%*>sc^E>C} zM_v7({DdF*`T1-EJoxdR3K*uu>(loozG7EbSMxVFH#dA98ykz5 zKR7tZHo!ukD}HeNswOQK3t_C?-rmy0#6-;aiHV8qTYrB)Gkbe`sivleuZM?+qaHu< zQc_aFyrZKd=GE2J#f*=-Us+jUUTtkH^P8HQqRvlCOJi1Zb2GCR7Z(G$ZfIzTD*yWW znv#=~d0b*FqUH(;3S!2`_(I)HPfv54ot>S`#`r`%L^FQ3+fAsm`uciiudS_-8vkmp zj}{*}KR!MttcmbJ9-^|cl4FJsvEc9S?lKqb$;rt88+liJm77TCf6Tw3=D(Dbl)&18 zJ&E0JXTDl{6u+^tk$uGa1;3zh*1xy-uwPYG#eH8?RK#}G{0oNiBR4mf;6q_y;g|4X z5BAkui)(OkkABw*K5BhZV*+a``s}^^k6M4V@n2kAP-bQ(^HqG{>yfr5VKWjwYJGWm znPz8aX?}j5=H});)WX67O-)Tvad9#42bPwWXnlR1`D$MWUxKCLN3CG(!t?j?75qK! zm3_>K<>lpJ?R&NSo}M0_S5fB>_FZ~)cz8$~8yg(|+1VM#;q&?ai#OPR6)VOKYObuT zjMrAIui>b)w3KTf@nfyf<|UXJ>K-|~zrQE1*ZV2yi8&NM9@>zDuTVV1@_`TX@yqdB zIQ&95!t0F!())oAhVQ7N`CuF=V_1t literal 0 HcmV?d00001 diff --git a/static/imgs/icons/favicon_16x16_next.png b/static/imgs/icons/favicon_16x16_next.png new file mode 100644 index 0000000000000000000000000000000000000000..7a2849eb95bcc185f71ea342101374fac0d28aef GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstUx|vage(c z!@6@aFM*u20G|+7pUlDq3l_Y1@q(F|dCQh96DCY}`0yc6^6J&A8#it|c<`XOxcHqr zcb+_XvUKTEPEJloN5`{g&lVOIe){z3)TvYF&!7MCPx#T~JI^MNDaN`}_O(`T35Hj@sJV@$vB*8X5oq0BdV& z1qB5T4i4Vl-ie8cTU%Q)GBT&9r{(44_4W1Q;^OM+>MkxWp`oF2a&kF2IUyk-N=iz8 zetyf#%fG+B($dmoWMmgyuCD+900DGTPE!Ct=GbNc007}hL_t(I%e|AqlENSmL|X|= z0AmC~NTU1yzqw%6+JMN>K2gl0p=KK3TRN92>P&=drYZ14`GkHp`Y8J|-Ex2xmL|9y zxWJ5l{Fk5nc+UYY=qM?ve*@&RkdziRU>&CYyhw`*prO_C@Bmf?y4aCePQaxKSYr{= z`#w21JK!!GSKPStnA?EhW}yb4;`Z1E=z*aPTw$Alqz&8Jav;?iRsq}#khFro0qo!) z$)g13z_xh3c4{A{&SwEU`gx9l5wFmwMdd&W{z7@Aa^Q^E;XO+9m#fkNx+~