├── .deepsource.toml ├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report-----.md │ └── feature-request-----.md └── workflows │ ├── beta.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_zh.md ├── _config.yml ├── gulpfile.js ├── index.js ├── languages ├── en.yml ├── zh-CN.yml └── zh-TW.yml ├── layout ├── _partial │ ├── archives.ejs │ ├── author.ejs │ ├── categories.ejs │ ├── footer.ejs │ ├── head.ejs │ ├── left-aside.ejs │ ├── nav.ejs │ ├── pagination.ejs │ ├── plugins │ │ ├── comments │ │ │ ├── gitalk.ejs │ │ │ ├── livere.ejs │ │ │ ├── valine.ejs │ │ │ └── waline.ejs │ │ ├── latex.ejs │ │ └── lightbox.ejs │ ├── recent-post.ejs │ ├── right-aside.ejs │ ├── scrollbutton.ejs │ ├── tags.ejs │ └── toc-card.ejs ├── about.ejs ├── archive.ejs ├── artitalk.ejs ├── categories.ejs ├── category.ejs ├── index.ejs ├── layout.ejs ├── links.ejs ├── post.ejs ├── tag.ejs └── tags.ejs ├── lib ├── lazyload.js ├── mergeConfig.js └── minify │ ├── minifyCSS.js │ ├── minifyHTML.js │ └── minifyJS.js ├── package.json ├── scripts ├── generators │ ├── pagerouter.js │ └── search.js ├── helpers │ ├── count.js │ └── load.js ├── highlight │ └── replace.js ├── index.js └── tag │ └── note.js ├── source ├── css │ ├── _base │ │ ├── color.styl │ │ ├── highlight.styl │ │ ├── index.styl │ │ └── reset.styl │ ├── _mixins │ │ └── index.styl │ ├── _pages │ │ ├── about.styl │ │ ├── archives.styl │ │ ├── categories.styl │ │ ├── index.styl │ │ ├── rewrite.styl │ │ ├── tags.styl │ │ └── widgets │ │ │ ├── archive.styl │ │ │ ├── author.styl │ │ │ ├── button.styl │ │ │ ├── card.styl │ │ │ ├── categories.styl │ │ │ ├── columns.styl │ │ │ ├── container.styl │ │ │ ├── footer.styl │ │ │ ├── friends.styl │ │ │ ├── nav.styl │ │ │ ├── pagination.styl │ │ │ ├── post.styl │ │ │ ├── postlist.styl │ │ │ ├── recentposts.styl │ │ │ ├── search.styl │ │ │ ├── section.styl │ │ │ ├── tags.styl │ │ │ └── toc.styl │ ├── _variables │ │ └── index.styl │ └── main.styl └── js │ ├── lib │ ├── busuanzi.min.js │ ├── lightbox │ │ ├── baguetteBox.min.css │ │ └── baguetteBox.min.js │ ├── lozad.min.js │ ├── md5.min.js │ └── prism │ │ ├── prism-coy.min.css │ │ ├── prism-dark.min.css │ │ ├── prism-funky.min.css │ │ ├── prism-line-numbers.min.css │ │ ├── prism-okaidia.min.css │ │ ├── prism-solarizedlight.min.css │ │ ├── prism-tomorrow.min.css │ │ ├── prism-twilight.min.css │ │ └── prism.min.css │ └── main.js └── src └── scripts ├── console.ts ├── darkMode.ts ├── index.d.ts ├── main.ts ├── menuButton.ts ├── popButton.ts ├── rollup.config.js ├── scrollUp.ts ├── search.ts └── tsconfig.json /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "javascript" 5 | enabled = true -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "plugin:lodash-template/all"], 3 | "parserOptions": { 4 | "ecmaVersion": 2020, 5 | "sourceType": "module" 6 | }, 7 | "overrides": [ 8 | { 9 | "files": ["*.ejs"], 10 | "processor": "lodash-template/html", 11 | "parserOptions": { 12 | "templateSettings": { 13 | "evaluate": "(?:(?:<%_)|(?:<%(?!%)))([\\s\\S]*?)[_\\-]?%>", 14 | "interpolate": "<%-([\\s\\S]*?)[_\\-]?%>", 15 | "escape": "<%=([\\s\\S]*?)[_\\-]?%>" 16 | } 17 | } 18 | } 19 | ], 20 | "ignorePatterns": ["src/scripts/*.js", "**/main.js"], 21 | "rules": { 22 | "semi": 0, 23 | "no-var": "error", 24 | // hack for ejs lint 25 | "no-undef": 0, 26 | "init-declarations": 2, 27 | "camelcase": 0, 28 | "quotes": ["error", "single"], 29 | "indent": ["error", 2, { "SwitchCase": 1 }], 30 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 31 | "comma-spacing": [2, { "before": false, "after": true }], 32 | "comma-style": [2, "last"], 33 | "lodash-template/prefer-escape-template-interpolations": 0 34 | }, 35 | "env": { 36 | "browser": true, 37 | "node": true, 38 | "es6": true 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report-----.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 问题报告 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: songhn233 7 | 8 | --- 9 | 10 | **Describe the bug 描述问题** 11 | A clear and concise description of what the bug is. 简要描述所遇到的问题 12 | 13 | **To Reproduce 如何复现** 14 | Steps to reproduce the behavior. 简要描述复现步骤或提供最小可复现 demo 15 | 16 | **Environment 使用环境** 17 | - Hexo Version 使用 Hexo 版本 18 | - Theme Version 使用主题版本 19 | - Browser 浏览器版本(可选) 20 | 21 | 22 | **Additional context 额外信息** 23 | Add any other context about the problem here. 额外需要说明的内容 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request-----.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 特性请求 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe. 你的特性请求是因为什么问题?** 11 | A clear and concise description of what the problem is. 简要描述你需要增加新特性以解决的问题或处理的场景。 12 | 13 | **Describe the solution you'd like 描述新特性的需求** 14 | A clear and concise description of what you want to happen. 简要描述新特性需要满足的功能和基本的设计。 15 | 16 | 17 | **Additional context 额外内容** 18 | Add any other context or screenshots about the feature request here. 额外需要补充的信息 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/beta.yml: -------------------------------------------------------------------------------- 1 | name: BetaReleaseWorkflow 2 | on: 3 | push: 4 | tags: 5 | - beta* 6 | 7 | jobs: 8 | publish-npm: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | with: 14 | ref: master 15 | - name: Stepup Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: '12.x' 19 | registry-url: 'https://registry.npmjs.org/' 20 | - name: NPM Publish 21 | run: | 22 | npm install 23 | npm publish --tag beta 24 | env: 25 | NODE_AUTH_TOKEN: '${{ secrets.npm_token }}' -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: ReleaseWorkflow 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | 7 | jobs: 8 | publish-npm: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | with: 14 | ref: master 15 | - name: Stepup Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: '12.x' 19 | registry-url: 'https://registry.npmjs.org/' 20 | - name: NPM Publish 21 | run: | 22 | npm install 23 | npm publish 24 | env: 25 | NODE_AUTH_TOKEN: '${{ secrets.npm_token }}' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | *.log 4 | yarn.lock 5 | package.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 theme-kaze 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

Hexo Theme Kaze

5 |

A simple, responsive Hexo theme

6 |

English | 中文

7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |

21 | 22 | --- 23 | ## Preview 24 | 25 |

26 | 27 |

28 | 29 | ## Introduction 30 | 31 | Kaze is a simple, responsive and modern Hexo theme, designed by [theme-kaze](https://github.com/theme-kaze) 32 | 33 | 34 | ## Feature 35 | 36 | + Responsive design, adapt to mobile phones, tablets, computers and other devices 37 | + Front-end performance optimization 38 | + Image lazy loading, can be used with thumbnails to get a better experience 39 | + Resource minify, speed up access speed 40 | + minimize the use of JS libraries such as Jquery 41 | + Sidebar widgets, such as recent articles, author cards 42 | + Dark mode, enjoy the comfort of the night 43 | + Code highlight, support prismjs 44 | + Formula rendering, support `katex` and `mathjax` 45 | + Comments, integrated `valine`, `gitalk`, `livere` 46 | + PV/UV statistics and google analytics support 47 | ## Demo 48 | 49 | + [Demo](https://demo.theme-kaze.top/) 50 | + [0x4qE's Blog](https://0727.site) 51 | 52 | ## Installation 53 | 54 | **We recommend using Hexo 5.0.0 and above for a better experience** 55 | 56 | ### Install by npm/yarn 57 | 58 | In version 5.0.0 and above, you can directly enter this command to install 59 | 60 | ```bash 61 | npm install hexo-theme-kaze 62 | ``` 63 | 64 | then change `your site/_config.yml` 65 | 66 | ```yaml 67 | theme: kaze 68 | ``` 69 | ### Other method 70 | 71 | Enter this command under `your site/themes` 72 | 73 | ```bash 74 | git clone https://github.com/theme-kaze/hexo-theme-kaze.git 75 | ``` 76 | 77 | Or download compression package and unzip under `your site/themes`, rename `hexo-theme-kaze` to `kaze` 78 | 79 | > Renamed to `kaze` is to maintain consistency with installation by `npm/yarn` 80 | 81 | ## document 82 | 83 | [Configuration document](https://demo.theme-kaze.top/document/) 84 | 85 | ## Issue template 86 | 87 | If you have any `bug` or suggestion, please send us `issue`! 88 | 89 | You can see issue template details when creating new issues. 90 | 91 | ## Contributors 92 | 93 | + [@0x4qE](https://github.com/0x4qE) 94 | + [@songhn233](https://github.com/songhn233) 95 | 96 | ### Special Thanks 97 | 98 | This theme references to the design of [SukkaW's blog](https://blog.skk.moe/) 99 | 100 | ## License 101 | 102 | Open sourced under the MIT License 103 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

hexo-theme-kaze

5 |

一个简洁,响应式的 Hexo 主题

6 |

中文 | English

7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |

21 | 22 | --- 23 | ## 预览 24 | 25 | ![效果展示](https://img.songhn.com/img/gallery.png?imageslim) 26 | 27 | ## 简介 28 | 29 | Kaze 是一个简洁、响应式、快速的Hexo主题,由 [theme-kaze](https://github.com/theme-kaze) 开发维护。 30 | 31 | ## 特性 32 | 33 | + 响应式设计,适配桌面端、平板、手机等各种设备 34 | + 前端性能优化,加载快速,眨眼之间即可加载完成 35 | + 图片懒加载,应用懒加载技术加快页面的生成速度 36 | + 资源压缩,提升本地资源请求速度 37 | + 精简设计,不包含 JQuery 等额外库 38 | + 支持侧边栏小组件,例如最近文章,作者卡片 39 | + 暗黑模式,享受黑夜的魅力 40 | + 代码高亮,支持 prismjs 41 | + 公式渲染,支持 `katex` 和 `mathjax` 42 | + 评论系统,集成 `valine`、`gitalk` 和 `livere` 43 | + 访问量统计和谷歌分析支持 44 | ## Demo演示 45 | 46 | + [Demo](https://demo.theme-kaze.top/) 47 | + [0x4qE's Blog](https://0727.site) 48 | 49 | ## 安装 50 | 51 | ### 直接通过 npm/yarn 安装 52 | 53 | 在 Hexo 5.0 以上版本中您可以直接通过输入 54 | 55 | ```bash 56 | npm install hexo-theme-kaze 57 | ``` 58 | 59 | 直接安装主题,接着修改 `your site/_config.yml` 60 | 61 | ```yaml 62 | theme: kaze 63 | ``` 64 | 65 | ### 其他方式 66 | 67 | 如果您有其他需要可以在 `your site/themes` 下输入 68 | 69 | ```bash 70 | git clone https://github.com/theme-kaze/hexo-theme-kaze.git 71 | ``` 72 | 73 | 或者下载主题压缩包在 `your site/themes` 下解压,并且将`hexo-theme-kaze`重命名为`kaze` 74 | 75 | > 重命名为 `kaze` 是为了与通过 `npm/yarn` 下载保持一致性 76 | 77 | ## 配置说明 78 | 79 | [主题使用文档](https://demo.theme-kaze.top/document/) 80 | 81 | ## issue格式 82 | 83 | 有任何的问题或者建议都可以向我们提 `issue`! 84 | 85 | ```markdown 86 | ## hexo版本以及您遇到的问题 87 | TODO 88 | ## 如何重现这个问题 89 | TODO 90 | ## 预期结果 91 | TODO 92 | ``` 93 | 94 | ## 贡献者 95 | 96 | + [@0x4qE](https://github.com/0x4qE) 97 | + [@songhn233](https://github.com/songhn233) 98 | 99 | ### 特别感谢 100 | 101 | 主题样式设计参考了 [SukkaW's blog](https://blog.skk.moe/) 102 | 103 | ## 开源许可 104 | 105 | 根据MIT许可开源 106 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | #------------------------ 2 | # Header config 3 | title: Theme Kaze 4 | author: theme-kaze 5 | # put the logo on the ${blog_path}/source/img/${picname}.png or use urls 6 | # logo_img: https://img.songhn.com/img/Y67gdd.png 7 | author_img: https://img.songhn.com/img/Y67gdd.png 8 | author_description: designed by theme-kaze 9 | #------------------------ 10 | # Navbar config 11 | #------------------------ 12 | menus: 13 | home: / 14 | archive: /archives 15 | tags: /tags 16 | categories: /categories 17 | about: /about 18 | friends: /links 19 | # artitalk: /shuoshuo # You can uncomment to add this route 20 | 21 | about: 22 | description: description 23 | social_links: 24 | # - { icon: icon, link: your link } 25 | 26 | #------------------------ 27 | # Links 28 | #------------------------ 29 | links: 30 | # name: 31 | # url: https://example.com 32 | # avatar: 33 | # description: 34 | #------------------------ 35 | # tip: if you want to use QQ avatar without giving away your QQ number, 36 | # you can use this api to get an encrypted url: 37 | # https://ptlogin2.qq.com/getface?appid=1006102&imgtype=3&uin=${yourQQNumber} 38 | # and use the encrypted url in the json 39 | #------------------------ 40 | 41 | #------------------------ 42 | # Post 43 | #------------------------ 44 | toc: 45 | showListNumber: false 46 | maxDepth: 6 47 | minDepth: 1 48 | 49 | copyright: 50 | enable: true 51 | writer: # if writer is empty we will use config.author as writer 52 | declare: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 协议。转载请注明出处! 53 | style: warning # the style uses note warning | danger | primary | info | success 54 | 55 | search: 56 | enable: false 57 | path: search.json 58 | field: posts 59 | searchContent: true 60 | 61 | og: 62 | enable: true 63 | title: true 64 | url: true 65 | image: true 66 | description: true 67 | article: true 68 | #------------------------ 69 | # Footer 70 | #------------------------ 71 | footer: 72 | copyYear: 2020 73 | # if showPoweredBy is ture, 'Powered by Hexo' will be seen on the footer 74 | showPoweredBy: true 75 | # if showThemeName is ture, 'Theme - Kaze' will be seen on the footer 76 | showThemeName: true 77 | #------------------------ 78 | # Record config 79 | # please put the gov image in ${yoursite}/img/beian.png 80 | RecordInfo: "" # your Record info such as '某ICP备xxx号' 81 | govRecordInfo: "" # your gov record info such as '某公网安备xxx号' 82 | govRecordUrl: "" # your gov record url 83 | #------------------------ 84 | # pv / uv statistics config 85 | #------------------------ 86 | statistics: 87 | enable: false 88 | type: busuanzi # now version only supports busuanzi 89 | pv: 90 | enable: true 91 | style: 本站总访问量{}次 # the style will be shown as $1{pv}$2 92 | uv: 93 | enable: true 94 | style: 本站总访客数{}次 # the style will be shown as $1{uv}$2 95 | 96 | widgets: 97 | showWidgetsMobiles: "none" 98 | #------------------------ 99 | # animation config 100 | #------------------------ 101 | # if scrollUpAnimation is true, there will be scroll-up animation. 102 | scrollUpAnimation: true 103 | 104 | #------------------------ 105 | # comment config 106 | #------------------------ 107 | comment: 108 | enable: false 109 | type: valine # valine | gitalk | livere | disqus | we recommend valine | waline 110 | # gitalk config details can see in https://github.com/gitalk/gitalk/blob/master/readme-cn.md 111 | # waline config details can see in https://waline.js.org 112 | valine: 113 | appId: 114 | appKey: 115 | placeholder: Just go go 116 | path: window.location.pathname 117 | avatar: mp 118 | meta: ["nick", "mail", "link"] 119 | pageSize: 10 120 | visitor: false 121 | highlight: true 122 | recordIP: false 123 | serverURLs: # leancloud国内自定义域名 124 | emojiCDN: 125 | emojiMaps: null 126 | enableQQ: false 127 | requiredFields: [] 128 | gitalk: 129 | clientID: 130 | clientSecret: 131 | repo: 132 | owner: 133 | admin: 134 | id: location.href 135 | distractionFreeMode: false 136 | # en | zh-CN | zh-TW 137 | language: navigator.language || navigator.userLanguage 138 | labels: ['Gitalk'] 139 | perPage: 10 140 | livere: 141 | uid: 142 | waline: 143 | serverURL: 144 | path: window.location.pathname 145 | avatar: mp 146 | meta: ["nick", "mail", "link"] 147 | requiredMeta: [] 148 | lang: zh-CN 149 | dark: html[data-user-color-scheme="dark"] 150 | login: enable 151 | wordLimit: 0 152 | pageSize: 10 153 | locale: 154 | placeholder: Just go go 155 | 156 | #------------------------ 157 | # latex config 158 | #------------------------ 159 | # choose true to use latex by mathjax or katex 160 | # warning: latex rendering will put lots of loading burden on page loading 161 | latex: 162 | enable: false 163 | engine: mathjax # mathjax | katex 164 | # for better rendering effect, when you choose mathjax, you can use it directly but you will lose some effect 165 | # so you can use hexo-renderer-kramed 166 | # when you choose katex, you must use hexo-renderer-markdown-it-plus or other render engine 167 | global: false 168 | # when you choose false, you can use latex by `latex: true` in post front-matter 169 | 170 | #------------------------ 171 | # lazyload config 172 | #------------------------ 173 | lazyload: 174 | enable: true 175 | loadingImg: 176 | 177 | #------------------------ 178 | # plugins config 179 | #------------------------ 180 | lightbox: 181 | enable: true 182 | # If your hexo version is below 5.0.0, please upgrade first to use this config 183 | # we support eight highlight themes, you can go to prism website (https://prismjs.com) for more information 184 | # theme: default | coy | dark | funky | okaidia | solarizedlight | tomorrow | twilight 185 | prism: 186 | theme: default 187 | darkTheme: tomorrow 188 | # show the number of words in posts 189 | wordcount: 190 | enable: true 191 | # Analytics config 192 | analytics: 193 | enable: false 194 | type: google # google 195 | google: 196 | id: # you can see more information in https://analytics.google.com/ 197 | # Doc:https://artitalk.js.org/ 198 | artitalk: 199 | enable: false 200 | appId: 201 | appKey: 202 | #------------------------ 203 | # minify config 204 | # css minify uses autoprefixer and clean-css 205 | # javascript minify uses uglify-es 206 | # html minify uses html-minifier 207 | #------------------------ 208 | minify: 209 | enable: false 210 | css: true 211 | js: true 212 | html: true 213 | #------------------------ 214 | # theme design config 215 | #------------------------ 216 | # the config of theme colors and styles 217 | # you can modify these presets to design different styles 218 | color: 219 | text-color: "#3c4858" 220 | text-strong-color: "#2f3d4e" 221 | text-light-color: "#60656a" 222 | divider-color: "#e6e8ee" 223 | title-color: "#475b6d" 224 | link-color: "#3273dc" 225 | link-hover-color: "#6596e5" 226 | info-text-color: "#60656a" 227 | widget-background-color: "#fff" 228 | body-background-color: "#f2f5f8" 229 | border-color: "#e1e4e9" 230 | pre-color: "#2d2d2d" 231 | code-color: "#50687c" 232 | code-background-color: "#e9eaf0" 233 | 234 | font: 235 | font-size: 15px # global font-size 236 | font-family: '-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","PingFang SC","Microsoft YaHei",sans-serif' # global font-family 237 | 238 | #------------------------ 239 | # cdn config 240 | #------------------------ 241 | cdn: 242 | mathjax: //cdn.jsdelivr.net/npm/mathjax@3.0.5/es5/tex-svg.js 243 | katex: //cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css 244 | gitalk: 245 | css: //cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css 246 | js: //cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js 247 | valine: //unpkg.com/valine/dist/Valine.min.js 248 | livere: //cdn-city.livere.com/js/embed.dist.js 249 | waline: 250 | js: //unpkg.com/@waline/client@v2/dist/waline.js 251 | css: //unpkg.com/@waline/client@v2/dist/waline.css 252 | baguetteBox: /js/lib/lightbox 253 | lozad: /js/lib/lozad.min.js 254 | prism: /js/lib/prism/ 255 | busuanzi: /js/lib/busuanzi.min.js 256 | artitalk: https://cdn.jsdelivr.net/npm/artitalk 257 | md5: /js/lib/md5.min.js 258 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const eslint = require('gulp-eslint'); 3 | const shell = require('gulp-shell'); 4 | 5 | gulp.task('lint:js', () => gulp.src([ 6 | './source/js/**/*.js' 7 | ]).pipe(eslint()) 8 | .pipe(eslint.format()) 9 | .pipe(eslint.failAfterError())); 10 | 11 | gulp.task('lint:ejs', shell.task(['ejslint ./layout/**/*.ejs'])); 12 | 13 | gulp.task('default', gulp.series('lint:js', 'lint:ejs')); 14 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | console.log('welcome to use theme kaze!') 2 | -------------------------------------------------------------------------------- /languages/en.yml: -------------------------------------------------------------------------------- 1 | home: 2 | title: Home 3 | 4 | archive: 5 | title: Archive 6 | 7 | about: 8 | title: About 9 | 10 | friends: 11 | title: Friends 12 | 13 | artitalk: 14 | title: artitalk 15 | 16 | posts: 17 | title: Posts 18 | 19 | categories: 20 | title: Categories 21 | total: Total posts 22 | 23 | tags: 24 | title: Tags 25 | total: Total tags 26 | 27 | hottags: 28 | title: hot tags 29 | 30 | readmore: 31 | title: Read Details 32 | 33 | recentposts: 34 | title: Recent Posts 35 | 36 | toc: 37 | title: TOC 38 | 39 | prev_page: 40 | title: Prev 41 | 42 | next_page: 43 | title: Next 44 | 45 | prev_post: 46 | title: Prev 47 | 48 | next_post: 49 | title: Next 50 | 51 | words_count: 52 | title: words 53 | 54 | min2read: 55 | title: mins 56 | -------------------------------------------------------------------------------- /languages/zh-CN.yml: -------------------------------------------------------------------------------- 1 | home: 2 | title: 首页 3 | 4 | archive: 5 | title: 归档 6 | 7 | about: 8 | title: 关于 9 | 10 | friends: 11 | title: 友链 12 | 13 | artitalk: 14 | title: 说说 15 | 16 | posts: 17 | title: 文章 18 | 19 | categories: 20 | title: 分类 21 | total: 共计 篇文章 22 | 23 | tags: 24 | title: 标签 25 | total: 共计 个标签 26 | 27 | hottags: 28 | title: 热门标签 29 | 30 | readmore: 31 | title: 继续阅读 32 | 33 | recentposts: 34 | title: 最近文章 35 | 36 | toc: 37 | title: 目录 38 | 39 | prev_page: 40 | title: 上一页 41 | 42 | next_page: 43 | title: 下一页 44 | 45 | prev_post: 46 | title: 上一篇 47 | 48 | next_post: 49 | title: 下一篇 50 | 51 | words_count: 52 | title: 字 53 | 54 | min2read: 55 | title: 分钟 56 | -------------------------------------------------------------------------------- /languages/zh-TW.yml: -------------------------------------------------------------------------------- 1 | # 繁體中文由郭桓桓翻譯 2 | # Copyright (c) 2021 KuoHuanHuan, 3 | # permission of re-publish is granted for "hexo-theme-kaze" project~ 4 | 5 | home: 6 | title: 首頁 7 | 8 | archive: 9 | title: 存檔 10 | 11 | about: 12 | title: 關於 13 | 14 | friends: 15 | title: 友鏈 16 | 17 | artitalk: 18 | title: 小語 19 | 20 | posts: 21 | title: 文章 22 | 23 | categories: 24 | title: 分類 25 | total: 共計 篇文章 26 | 27 | tags: 28 | title: 標籤 29 | total: 共計 個標籤 30 | 31 | hottags: 32 | title: 熱門標籤 33 | 34 | readmore: 35 | title: 繼續閱讀 36 | 37 | recentposts: 38 | title: 最新文章 39 | 40 | toc: 41 | title: 目錄 42 | 43 | prev_page: 44 | title: 上一頁 45 | 46 | next_page: 47 | title: 下一頁 48 | 49 | prev_post: 50 | title: 上一篇 51 | 52 | next_post: 53 | title: 下一篇 54 | 55 | words_count: 56 | title: 個字 57 | 58 | min2read: 59 | title: 分鐘 60 | -------------------------------------------------------------------------------- /layout/_partial/archives.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | <%- __('archive.title') %> 7 |
8 |
9 | <% let archiveYear = ''; %> 10 | <% let count = 0; %> 11 | <% site.posts.sort('date', -1).forEach(post => { %> 12 | <% if (date(post.date, 'YYYY') != archiveYear) { %> 13 | <% if (count != 0) { %> 14 | 17 | <%= archiveYear %> 18 | <%= count %> 19 | 20 | <% } %> 21 | <% count = 1; %> 22 | <% archiveYear = date(post.date, 'YYYY'); %> 23 | <% } else { %> 24 | <% count++; %> 25 | <% } %> 26 | <% }); %> 27 | <% if (count != 0) { %> 28 | 31 | <%= archiveYear %> 32 | <%= count %> 33 | 34 | <% } %> 35 |
36 |
-------------------------------------------------------------------------------- /layout/_partial/author.ejs: -------------------------------------------------------------------------------- 1 | <% if(theme.author_img) { %> 2 | author avatar 8 | <% } %> 9 |

<%- theme.author || config.author %>

10 |

<%- theme.author_description || config.description %>

11 |
12 | 15 | <%- site.posts.length %> 16 | <%- __('posts.title') %> 17 | 18 | 21 | <%- site.categories.length %> 22 | <%- __('categories.title') %> 23 | 24 | 27 | <%- site.tags.length %> 28 | <%- __('tags.title') %> 29 | 30 |
31 | <% if(theme.about.social_links) { %> 32 |
33 | <% for(const item of theme.about.social_links) { %> 34 |
35 | 36 | 37 | 38 |
39 | <% } %> 40 |
41 | <% } %> -------------------------------------------------------------------------------- /layout/_partial/categories.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | <%- __('categories.title') %> 7 |
8 |
9 | <% for(const item of site.categories.data) { %> 10 | 11 |
12 | <%= item.slug %> 13 | <%= item.posts.length %> 14 |
15 |
16 | <% } %> 17 |
18 |
-------------------------------------------------------------------------------- /layout/_partial/footer.ejs: -------------------------------------------------------------------------------- 1 | 80 | -------------------------------------------------------------------------------- /layout/_partial/head.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 13 | 16 | 19 | <%- page.title || theme.title %> 20 | <% if(theme.og && theme.og.enable) { %> 21 | <% if(theme.og.title) { %> 22 | 25 | <% } %> 26 | <% if(theme.og.url) { %> 27 | 30 | <% } %> 31 | <% if(theme.og.image && (page.banner_img || theme.author_img)) { %> 32 | 35 | <% } %> 36 | <% if(theme.og.description && (page.excerpt || theme.description || config.description)) { %> 37 | 40 | <% } %> 41 | <% if(theme.og.article && is_post()) { %> 42 | 45 | 48 | 51 | 54 | <% if(page.tags.data) { %> 55 | <% for(let item of page.tags.data) { %> 56 | 59 | <% } %> 60 | <% } %> 61 | <% } %> 62 | <% } %> 63 | <%# preload %> 64 | <%- preload_css('//at.alicdn.com/t/font_1946621_i1kgafibvw.css') %> 65 | <%- preload_css('//at.alicdn.com/t/font_1952792_89b4ac4k4up.css') %> 66 | <%- preload_css(url_for('css/main.css')) %> 67 | <% if(theme.comment.type === 'waline' && theme.comment.enable) { %> 68 | <% if(is_post()) { %> 69 | <%- preload_css(url_for(theme.cdn.waline.css)) %> 70 | <%- preload_js(url_for(theme.cdn.waline.js)) %> 71 | <% } else { %> 72 | <%- prefetch_css(url_for(theme.cdn.waline.css)) %> 73 | <%- prefetch_js(url_for(theme.cdn.waline.js)) %> 74 | <% } %> 75 | <% } %> 76 | 77 | <%# main css %> 78 | <%- ex_css(url_for('css/main.css')) %> 79 | <%# default icon %> 80 | <%- ex_css('//at.alicdn.com/t/font_1946621_i1kgafibvw.css') %> 81 | <%# social icon %> 82 | <%- ex_css('//at.alicdn.com/t/font_1952792_89b4ac4k4up.css') %> 83 | <%# comments css %> 84 | <% if(theme.comment.type === 'waline' && theme.comment.enable && is_post()) { %> 85 | <%- ex_css(url_for(theme.cdn.waline.css)) %> 86 | <% } %> 87 | <% if(theme.lightbox.enable && is_post()) { %> 88 | <%- ex_css(url_for(theme.cdn.baguetteBox + '/baguetteBox.min.css')) %> 89 | <% } %> 90 | 114 | <% if(config.prismjs) { %> 115 | <% if(config.prismjs.enable && !config.highlight.enable) { %> 116 | <% let prismTheme = theme.prism.theme || 'default' %> 117 | <% prismTheme = (prismTheme === 'default') ? 'prism' : ('prism-' + prismTheme) %> 118 | <% const themeUrl = url_for(theme.cdn.prism + prismTheme + '.min.css') %> 119 | <% if (theme.prism.darkTheme) { %> 120 | <% let darkPrismTheme = theme.prism.darkTheme || 'default' %> 121 | <% darkPrismTheme = (darkPrismTheme === 'default') ? 'prism' : ('prism-' + darkPrismTheme) %> 122 | <% const darkThemeUrl = url_for(theme.cdn.prism + darkPrismTheme + '.min.css') %> 123 | 141 | <% } %> 142 | <% if(config.prismjs.line_number && config.prismjs.preprocess) { %> 143 | <% const lineUrl = theme.cdn.prism + 'prism-line-numbers.min.css' %> 144 | <%- ex_css(url_for(lineUrl)) %> 145 | <% } %> 146 | <% } %> 147 | <% } else if(theme.prism.theme) { %> 148 | <% console.log('INFO: your Hexo version < 5.0.0 and could not use prismjs') %> 149 | <% } %> 150 | 179 | <% if(config.prismjs && config.prismjs.enable && theme.prism && theme.prism.darkTheme) { %> 180 | 204 | <% } else { %> 205 | 226 | <% } %> 227 | <%# TODO: New Prefetch Plan %> 228 | <% if(theme.lightbox.enable) { %> 229 | <%- preload_js(url_for(theme.cdn.baguetteBox + '/baguetteBox.min.js')) %> 230 | <%- preload_css(url_for(theme.cdn.baguetteBox + '/baguetteBox.min.css')) %> 231 | <% } %> 232 | <% if(theme.lazyload.enable) { %> 233 | <%- preload_js(url_for(theme.cdn.lozad)) %> 234 | <% } %> 235 | <%# end preload %> 236 | <%# prefetch %> 237 | <% if(theme.latex.enable) { %> 238 | <% const engine = theme.latex.engine; %> 239 | <%- prefetch_js(theme.cdn[engine]) %> 240 | <% } %> 241 | <% if(theme.comment.enable) { %> 242 | <% const type = theme.comment.type; %> 243 | <%- prefetch_js(theme.cdn[type].js ? theme.cdn[type].js : theme.cdn[type]) %> 244 | <% } %> 245 | <%# end prefetch %> 246 | 247 | -------------------------------------------------------------------------------- /layout/_partial/left-aside.ejs: -------------------------------------------------------------------------------- 1 |
2 | <%# display when two columns %> 3 | <% if(is_post()){ %> 4 |
5 |
6 | <%- partial('_partial/toc-card') %> 7 |
8 |
9 | <% } %> 10 | <%# categories card %> 11 |
12 | <%- partial('_partial/categories') %> 13 |
14 | <%# tags card %> 15 |
16 | <%- partial('_partial/tags') %> 17 |
18 | <%# display when is not in post %> 19 | <% if(!is_post()) { %> 20 |
21 | <%- partial('_partial/archives') %> 22 |
23 | <% } %> 24 |
-------------------------------------------------------------------------------- /layout/_partial/nav.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_partial/pagination.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_partial/plugins/comments/gitalk.ejs: -------------------------------------------------------------------------------- 1 | <% if(theme.comment.gitalk.clientID && theme.comment.gitalk.clientSecret && theme.comment.gitalk.repo && theme.comment.gitalk.owner && theme.comment.gitalk.admin) { %> 2 |
3 | <%- css(theme.cdn.gitalk.css) %> 4 | <%- js(theme.cdn.gitalk.js) %> 5 | <%- js(theme.cdn.md5) %> 6 | 22 | <% } %> -------------------------------------------------------------------------------- /layout/_partial/plugins/comments/livere.ejs: -------------------------------------------------------------------------------- 1 | <% if(theme.comment.livere.uid){ %> 2 |
6 | 18 |
19 | <% } %> -------------------------------------------------------------------------------- /layout/_partial/plugins/comments/valine.ejs: -------------------------------------------------------------------------------- 1 | <% if(theme.comment.valine.appId && theme.comment.valine.appKey) { %> 2 |
3 | 4 | 36 | <% } %> -------------------------------------------------------------------------------- /layout/_partial/plugins/comments/waline.ejs: -------------------------------------------------------------------------------- 1 | <% if(theme.comment.waline.serverURL) { %> 2 |
3 | 31 | <% } %> -------------------------------------------------------------------------------- /layout/_partial/plugins/latex.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | let flag = theme.latex.enable; 3 | if(flag) { 4 | if(is_page() || is_post()) { 5 | flag = theme.latex.global || page.latex; 6 | } else { 7 | flag = false; 8 | } 9 | } 10 | %> 11 | <% if(flag) { %> 12 | <% const engine = theme.latex.engine; %> 13 | <% if(engine === 'mathjax') { %> 14 | 21 | <%- js(theme.cdn.mathjax) %> 22 | <% } else if(engine === 'katex') { %> 23 | <%- css(theme.cdn.katex) %> 24 | <% } %> 25 | <% } %> -------------------------------------------------------------------------------- /layout/_partial/plugins/lightbox.ejs: -------------------------------------------------------------------------------- 1 | 23 | 29 | -------------------------------------------------------------------------------- /layout/_partial/recent-post.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | <%- __('recentposts.title') %> 7 |
8 |
9 | <% site.posts.sort('date', -1).slice(0, Math.min(4, site.posts.length)).forEach(post => { %> 10 |
11 |
<%= date(post.date) %>
12 |
<%= post.title %>
13 |
14 | <% }) %> 15 |
16 |
-------------------------------------------------------------------------------- /layout/_partial/right-aside.ejs: -------------------------------------------------------------------------------- 1 |
2 | <%# toc card %> 3 | <% if(is_post() && page.toc !== false) { %> 4 |
5 | <%- partial('_partial/toc-card') %> 6 |
7 | <% } %> 8 | <%# recent post %> 9 |
10 | <%- partial('_partial/recent-post') %> 11 |
12 | <%# archives card %> 13 | <% if(!is_post()) { %> 14 |
15 | <%- partial('_partial/archives') %> 16 |
17 | <% } %> 18 |
-------------------------------------------------------------------------------- /layout/_partial/scrollbutton.ejs: -------------------------------------------------------------------------------- 1 | <% if (!theme.scrollUpAnimation) { %> 2 | 8 | 9 | 10 | <% } else { %> 11 | 16 | 17 | 18 | <% } %> 19 | 24 | 25 | 26 | 31 | 32 | 33 | 38 | 39 | 40 | 45 | 46 | -------------------------------------------------------------------------------- /layout/_partial/tags.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | <%- __('hottags.title') %> 7 |
8 |
9 | <% site.tags.data.slice(0, Math.min(16, site.tags.data.length)).forEach(function(item){ %> 10 | 13 |
<%= item.name %>
14 |
15 | <% }) %> 16 |
17 |
-------------------------------------------------------------------------------- /layout/_partial/toc-card.ejs: -------------------------------------------------------------------------------- 1 |
2 | 5 | <%- __('toc.title') %> 6 |
7 | <%- toc(page.content, { list_number: theme.toc.showListNumber, max_depth: theme.toc.maxDepth, min_depth: theme.toc.minDepth }) %> -------------------------------------------------------------------------------- /layout/about.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = page.title || __('about.title') %> 2 |
3 | <% if(theme.author_img) { %> 4 | Blog Author Avatar 8 | <% } %> 9 |
10 |
<%= theme.author || config.author %>
11 | <% if(theme.about.description) { %> 12 |
<%= theme.about.description %>
13 | <% } %> 14 |
15 | <% if(theme.about.social_links) { %> 16 | <% for(const item of theme.about.social_links) { %> 17 |
18 | 19 | 20 | 21 |
22 | <% } %> 23 | <% } %> 24 |
25 |
26 |
27 |
28 |
<%- page.content %>
29 |
-------------------------------------------------------------------------------- /layout/archive.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = __('archive.title') %> 2 |
3 |

<%- __('archive.title') %>

4 |
5 |
6 | <% let archiveYear = ''; %> 7 | <% page.posts.sort('date', -1).forEach(post => { %> 8 | <% if (date(post.date, 'YYYY') != archiveYear) { %> 9 |
<%= date(post.date, 'YYYY') %>
10 | <% archiveYear = date(post.date, 'YYYY'); %> 11 | <% } %> 12 |
13 |
14 |
15 | 16 |
17 | 20 | <%= post.title %> 21 | 22 |
23 |
24 |
25 |
26 | <% }); %> 27 |
28 | <% if(page.total > 1 ) { %> 29 | <%- partial('_partial/pagination', { 30 | prev_label: __('prev_page.title'), next_label:__('next_page.title'), 31 | prev_link: page.prev_link, next_link: page.next_link, 32 | prev_title: null, next_title: null 33 | }) %> 34 | <% } %> -------------------------------------------------------------------------------- /layout/artitalk.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = __('artitalk.title') %> 2 | 3 | <% if(theme.artitalk.enable) { %> 4 |
5 | 6 | 17 | <% } %> -------------------------------------------------------------------------------- /layout/categories.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = __('categories.title') %> 2 |
3 |
6 | <%- __('categories.title') %> 7 |
8 |
9 | <%= __('categories.total').split(' ')[0] %> <%= site.posts.data.length %> <%= __('categories.total').split(' ')[1] %> 10 |
11 |
12 |
13 | <% for(const postList of site.categories.data) { %> 14 | 18 | <%= postList.slug %> 19 | 21 | <%= __('categories.total').split(' ')[0] %> <%= postList.posts.length %> <%= __('categories.total').split(' ')[1] %> 22 | 23 | 24 | <% } %> 25 |
-------------------------------------------------------------------------------- /layout/category.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = __('categories.title') %> 2 |
3 |
<%- __('categories.title') %> - <%- page.category %>
4 |
5 |
6 | <% let archiveYear = ''; %> 7 | <% page.posts.forEach(post => { %> 8 | <% if (date(post.date, 'YYYY') != archiveYear) { %> 9 |
<%= date(post.date, 'YYYY') %>
10 | <% archiveYear = date(post.date, 'YYYY'); %> 11 | <% } %> 12 |
13 |
14 |
15 | 16 |
17 | 20 | <%= post.title %> 21 | 22 |
23 |
24 |
25 |
26 | <% }); %> 27 |
28 | <% if(page.total > 1 ) { %> 29 | <%- partial('_partial/pagination', { 30 | prev_label: __('prev_page.title'), next_label:__('next_page.title'), 31 | prev_link: page.prev_link, next_link: page.next_link, 32 | prev_title: null, next_title: null 33 | }) %> 34 | <% } %> -------------------------------------------------------------------------------- /layout/index.ejs: -------------------------------------------------------------------------------- 1 | <% page.posts.forEach(post => { %> 2 |
3 | <% if(post.banner_img) { %> 4 | 8 | <%= post.title %> banner 14 | 15 | <% } %> 16 |
17 | 18 |

19 | <%= post.title %> 20 |

21 |
22 |
23 | <% if(post.excerpt) { %> 24 | <%= strip_html(post.excerpt) %> 25 | <% } else { %> 26 | <%= strip_html(truncate( post.content, { length : 120 })) %> 27 | <% } %> 28 |
29 | 60 |
61 |
62 | <% }); %> 63 | <% if(page.total > 1 ) { %> 64 | <%- partial('_partial/pagination', { 65 | prev_label: __('prev_page.title'), next_label:__('next_page.title'), 66 | prev_link: page.prev_link, next_link: page.next_link, 67 | prev_title: null, next_title: null 68 | }) %> 69 | <% } %> -------------------------------------------------------------------------------- /layout/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%- partial('_partial/head') %> 4 | 5 |
6 | <%# navbar %> 7 | <%- partial('_partial/nav.ejs') %> 8 | <%# search content %> 9 | 18 | <%# main content %> 19 |
20 |
21 |
22 | 29 |
30 | <%- body %> 31 |
32 | 35 |
36 |
37 |
38 |
39 | <%# footer %> 40 | <%- partial('_partial/footer.ejs') %> 41 | <%- partial('_partial/scrollbutton.ejs') %> 42 | <%# plugins %> 43 | <% if(theme.latex.enable) { %> 44 | <%- partial('_partial/plugins/latex.ejs') %> 45 | <% } %> 46 | <% if(theme.lightbox.enable && is_post()) { %> 47 | <%- partial('_partial/plugins/lightbox.ejs') %> 48 | <% } %> 49 | <%# javascript %> 50 | <%- ex_js(url_for('/js/main.js')) %> 51 | <% if(theme.footer.statistics.enable && theme.footer.statistics.type === 'busuanzi') { %> 52 | 55 | <% } %> 56 | <% if(theme.lazyload.enable) { %> 57 | 70 | 73 | <% } %> 74 | 76 | <% if(theme.analytics.enable && theme.analytics.type === 'google' && theme.analytics.google.id) { %> 77 | 87 | 94 | <% } %> 95 | <% if(theme.search && theme.search.enable && theme.search.path) { %> 96 | 99 | <% } %> 100 | 101 | 102 | -------------------------------------------------------------------------------- /layout/links.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = __('friends.title') %> 2 |
3 |

<%- __('friends.title') %>

4 |
5 |
6 | 33 |
34 | -------------------------------------------------------------------------------- /layout/post.ejs: -------------------------------------------------------------------------------- 1 | <% if(page.banner_img) { %> 2 |
3 | <%= page.title %> thumbnail 9 |
10 | <% } %> 11 |
12 |
13 |

14 | <%= page.title %> 15 |

16 |
17 |
18 | 25 | <% if(page.categories && page.categories.data.length) { %> 26 | 27 | <% for(const item of page.categories.data) { %> 28 | 33 | <% } %> 34 | <% } %> 35 | <% if(theme.wordcount.enable) { %> 36 | 37 | <%= wordcount(page.content) %> <%= __('words_count.title') %> 38 | <% } %> 39 |
40 | <% if(page.tags && page.tags.data.length) { %> 41 |
44 |
45 | 48 | 49 | <% page.tags.data.forEach((item, index) => { %> 50 | <% if(index > 0) { %> 51 | 52 | <% } %> 53 | 58 | <% }) %> 59 |
60 |
61 | <% } %> 62 | 63 |
66 | <%- page.content %> 67 |
68 |
69 | <% if(theme.copyright.enable) { %> 70 |
73 |

74 | 作者: 78 | <%= theme.copyright.writer || theme.author || config.author %> 79 | 80 |

81 |

82 | 文章链接: 86 | <%= page.permalink %> 87 | 88 |

89 |

版权声明:<%- theme.copyright.declare %>

90 |
91 | <% } %> 92 |
93 |
94 | <%- partial('_partial/pagination', { 95 | prev_label: __('prev_post.title'), next_label:__('next_post.title'), 96 | prev_link: page.prev ? page.prev.path : '', next_link: page.next ? page.next.path : '', 97 | prev_title: page.prev ? page.prev.title : '', next_title: page.next ? page.next.title : '' 98 | }) %> 99 | <% if(theme.comment.enable && page.comment !== false) { %> 100 |
103 |
评论
104 | <%- partial('_partial/plugins/comments/' + theme.comment.type) %> 105 |
106 | <% } %> 107 |
110 | <%- partial('_partial/toc-card') %> 111 |
-------------------------------------------------------------------------------- /layout/tag.ejs: -------------------------------------------------------------------------------- 1 | <% page.title = __('tags.title') %> 2 |
3 |
<%- __('tags.title') %> - <%- page.tag %>
4 |
5 |
6 | <% let archiveYear = ''; %> 7 | <% page.posts.forEach(post => { %> 8 | <% if (date(post.date, 'YYYY') != archiveYear) { %> 9 |
<%= date(post.date, 'YYYY') %>
10 | <% archiveYear = date(post.date, 'YYYY'); %> 11 | <% } %> 12 |
13 |
14 |
15 | 16 |
17 | 20 | <%= post.title %> 21 | 22 |
23 |
24 |
25 |
26 | <% }); %> 27 |
-------------------------------------------------------------------------------- /layout/tags.ejs: -------------------------------------------------------------------------------- 1 | <%# eslint-disable no-undef %> 2 | <% page.title = __('tags.title') %> 3 |
4 |
7 | <%= __('tags.title') %> 8 |
9 |
10 | <%= __('tags.total').split(' ')[0] %> <%= site.tags.data.length %> <%= __('tags.total').split(' ')[1] %> 11 |
12 |
13 |
14 |
15 |
16 | <% site.tags.data.sort((a, b) => (a.posts.data.length - b.posts.data.length)).reverse().forEach(function(item){ %> 17 | 20 |
<%= item.name %>
21 |
22 | <% }); %> 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /lib/lazyload.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* eslint-disable quotes */ 3 | 'use strict'; 4 | module.exports = hexo => { 5 | if(!hexo.theme.config.lazyload || !hexo.theme.config.lazyload.enable) { 6 | return; 7 | } 8 | hexo.extend.filter.register('after_post_render', data => { 9 | const loadingImg = hexo.theme.config.lazyload.loadingImg || "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E"; 10 | data.content = data.content.replace(//gi, (str, p1, p2, p3) => { 11 | if(/class="(.*?)"/gi.test(str)) { 12 | str = str.replace(/class="(.*?)"/gi, (classStr, p1) => classStr.replace(p1, `${p1} lozad post-image`)); 13 | return str.replace(//gi, (str, p1, p2, p3) => { 14 | return str.replace(p3, `${p3} srcset="${loadingImg}" data-src="${p2}"`); 15 | }); 16 | } 17 | if(p3) { 18 | return str.replace(p3, `${p3} srcset="${loadingImg}" data-src="${p2}" class="lozad post-image"`); 19 | } else { 20 | return str.replace(p1, `${p1} srcset="${loadingImg}" data-src="${p2}" class="lozad post-image"`); 21 | } 22 | }); 23 | }); 24 | }; -------------------------------------------------------------------------------- /lib/mergeConfig.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const path = require('path'); 3 | const { hexo: { version } } = require(path.normalize('../../../package.json')); 4 | const isObj = data => (data && typeof data === 'object' && !Array.isArray(data)); 5 | const mergeConfig = (result, ...data) => { 6 | data.forEach(file => Object.keys(file).forEach(item => { 7 | if(file[item] !== null && file[item] !== undefined) { 8 | if(isObj(file[item]) && isObj(result[item])) { 9 | mergeConfig(result[item], file[item]); 10 | } else { 11 | result[item] = file[item]; 12 | } 13 | } 14 | })); 15 | return result; 16 | }; 17 | module.exports = hexo => { 18 | if(parseInt(version[0]) >= 5) { 19 | return; 20 | } 21 | let dataConfig = {}; 22 | if(hexo.locals.get) { 23 | const data = hexo.locals.get('data'); 24 | if(data && data.kaze_config) { 25 | dataConfig = data.kaze_config; 26 | } 27 | } 28 | hexo.theme.config = mergeConfig({}, hexo.theme.config, dataConfig); 29 | }; -------------------------------------------------------------------------------- /lib/minify/minifyCSS.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict' 3 | const cleancss = require('clean-css') 4 | module.exports = (hexo) => { 5 | hexo.extend.filter.register('after_render:css', function (str) { 6 | const result = new cleancss({}).minify(str).styles 7 | return result 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /lib/minify/minifyHTML.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict'; 3 | const htmlminify = require('html-minifier').minify; 4 | module.exports = hexo => { 5 | hexo.extend.filter.register('after_render:html', function(str){ 6 | const result = htmlminify(str, { 7 | collapseWhitespace: true, 8 | minifyURLs: true, 9 | sortAttributes: true, 10 | sortClassName: true, 11 | minifyJS: true, 12 | minifyCSS: true 13 | }); 14 | return result; 15 | }); 16 | }; -------------------------------------------------------------------------------- /lib/minify/minifyJS.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /** 3 | * @deprecated 4 | */ 5 | 'use strict'; 6 | const UglifyJS = require('uglify-es'); 7 | module.exports = hexo => { 8 | hexo.extend.filter.register('after_render:js', function(str){ 9 | const res = UglifyJS.minify(str); 10 | return res.code; 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hexo-theme-kaze", 3 | "version": "1.1.0-beta6", 4 | "description": "hexo-theme-kaze", 5 | "scripts": { 6 | "lint": "eslint **/*.ejs --fix", 7 | "source:js": "rollup -c ./src/scripts/rollup.config.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/theme-kaze/hexo-theme-Kaze.git" 12 | }, 13 | "keywords": [ 14 | "hexo", 15 | "theme", 16 | "Kaze" 17 | ], 18 | "author": "theme-kaze", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/theme-kaze/hexo-theme-Kaze/issues" 22 | }, 23 | "homepage": "https://demo.theme-kaze.top/", 24 | "devDependencies": { 25 | "@babel/core": "^7.13.16", 26 | "@rollup/plugin-babel": "^5.3.0", 27 | "@rollup/plugin-typescript": "^8.2.1", 28 | "eslint": "^7.4.0", 29 | "eslint-plugin-lodash-template": "^0.19.0", 30 | "gulp": "^4.0.2", 31 | "gulp-eslint": "^6.0.0", 32 | "gulp-shell": "^0.8.0", 33 | "rollup": "^2.45.2", 34 | "rollup-plugin-terser": "^7.0.2", 35 | "tslib": "^2.2.0", 36 | "typescript": "^4.2.4" 37 | }, 38 | "dependencies": { 39 | "clean-css": "^4.2.3", 40 | "html-minifier": "^4.0.0", 41 | "uglify-es": "^3.3.9" 42 | }, 43 | "directories": { 44 | "lib": "lib" 45 | }, 46 | "files": [ 47 | "languages", 48 | "layout", 49 | "scripts", 50 | "source", 51 | "_config.yml", 52 | "_vendors.yml" 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /scripts/generators/pagerouter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | // generate categories router 4 | hexo.extend.generator.register('_categories', function(locals) { 5 | return { 6 | path : 'categories/index.html', 7 | data : locals.theme, 8 | layout: 'categories' 9 | }; 10 | }); 11 | 12 | // generate tags router 13 | hexo.extend.generator.register('_tags', function(locals) { 14 | return { 15 | path : 'tags/index.html', 16 | data : locals.theme, 17 | layout: 'tags' 18 | }; 19 | }); 20 | 21 | 22 | // generate links router 23 | hexo.extend.generator.register('_links', function(locals) { 24 | return { 25 | path : 'links/index.html', 26 | data : locals.theme, 27 | layout: 'links' 28 | }; 29 | }); 30 | 31 | // generate about router 32 | // about page should be created by users 33 | /*hexo.extend.generator.register('_about', function(locals) { 34 | return { 35 | path : 'about/index.html', 36 | data : locals.theme, 37 | layout: 'index' 38 | }; 39 | });*/ -------------------------------------------------------------------------------- /scripts/generators/search.js: -------------------------------------------------------------------------------- 1 | /* 2 | Source: https://github.com/forsigner/hexo-search/blob/master/index.js 3 | License: MIT License 4 | Modify: songhn for hexo-theme-kaze 5 | */ 6 | 7 | /* global hexo */ 8 | 'use strict' 9 | // eslint-disable-next-line camelcase 10 | const url_for = require('hexo-util').url_for.bind(hexo) 11 | hexo.extend.generator.register('_hexo_generator_search', function (locals) { 12 | const config = hexo.theme.config 13 | 14 | if (!config.search || !config.search.enable || !config.search.path) { 15 | return 16 | } 17 | 18 | const searchSource = config.search.field.trim() 19 | const posts = locals.posts.sort('-date') 20 | const pages = locals.pages 21 | let sources = [] 22 | if (searchSource != '' && searchSource != 'all') { 23 | if (searchSource == 'posts') { 24 | sources = posts.data 25 | } else if (searchSource == 'pages') { 26 | sources = pages.data 27 | } 28 | } else { 29 | sources = posts.data.concat(pages.data) 30 | } 31 | let data = [] 32 | sources.forEach((post) => { 33 | let categories = [] 34 | let tags = [] 35 | if (post.layout == 'post') { 36 | if (post.categories !== 'undefined') { 37 | post.categories.data.forEach(function (categorie) { 38 | categories.push(categorie.name) 39 | }) 40 | } 41 | if (post.tags !== 'undefined') { 42 | post.tags.data.forEach(function (tag) { 43 | tags.push(tag.name) 44 | }) 45 | } 46 | } 47 | data.push({ 48 | title: post.title, 49 | url: url_for(`${post.path}`), 50 | content: config.search.searchContent 51 | ? post.content.replace(/<[^<>]+>/g, '') 52 | : '', 53 | categories: categories, 54 | tags: tags, 55 | }) 56 | }) 57 | return { 58 | path: '/search.json', 59 | data: JSON.stringify(data), 60 | } 61 | }) 62 | -------------------------------------------------------------------------------- /scripts/helpers/count.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* reference: https://github.com/willin/hexo-wordcount */ 3 | let util = require('hexo-util'); 4 | let stripHTML = util.stripHTML; 5 | 6 | let counter = function (content) { 7 | content = stripHTML(content); 8 | const cn = (content.match(/[\u4E00-\u9FA5]/g) || []).length; 9 | const en = (content.replace(/[\u4E00-\u9FA5]/g, '').match(/[a-zA-Z0-9_\u0392-\u03c9\u0400-\u04FF]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af\u0400-\u04FF]+|[\u00E4\u00C4\u00E5\u00C5\u00F6\u00D6]+|\w+/g) || []).length; 10 | return [cn, en]; 11 | }; 12 | 13 | hexo.extend.helper.register('min2read', function (content, { cn = 300, en = 160 } = {}) { 14 | let len = counter(content); 15 | let readingTime = len[0] / cn + len[1] / en; 16 | return readingTime < 1 ? '1' : parseInt(readingTime, 10); 17 | }); 18 | 19 | hexo.extend.helper.register('wordcount', function (content) { 20 | let len = counter(content); 21 | let count = len[0] + len[1]; 22 | if (count < 1000) { 23 | return count; 24 | } 25 | return Math.round(count / 100) / 10 + 'k'; 26 | }); 27 | 28 | hexo.extend.helper.register('totalcount', function (site) { 29 | let count = 0; 30 | site.posts.forEach(function (post) { 31 | let len = counter(post.content); 32 | count += len[0] + len[1]; 33 | }); 34 | if (count < 1000) { 35 | return count; 36 | } 37 | return Math.round(count / 100) / 10 + 'k'; 38 | }); -------------------------------------------------------------------------------- /scripts/helpers/load.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | hexo.extend.helper.register( 3 | 'preload_css', 4 | (url, isCross) => 5 | `` 8 | ) 9 | 10 | hexo.extend.helper.register( 11 | 'preload_js', 12 | (url) => `` 13 | ) 14 | 15 | hexo.extend.helper.register( 16 | 'prefetch_js', 17 | (url) => `` 18 | ) 19 | 20 | hexo.extend.helper.register( 21 | 'prefetch_css', 22 | (url) => `` 23 | ) 24 | 25 | hexo.extend.helper.register( 26 | 'ex_css', 27 | (url) => `` 28 | ) 29 | 30 | hexo.extend.helper.register('ex_js', (url) => ``) 31 | -------------------------------------------------------------------------------- /scripts/highlight/replace.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* 3 | TODO: add highlight.js config 4 | */ 5 | 'use strict'; 6 | hexo.extend.filter.register('after_post_render', (data) => { 7 | // delete
, remain the
...
8 | // $4 is the fourth matchment in the RegExp below, exactly the code block 9 | data.content = data.content.replace(/(.*?)<\/pre>(.*?)
(.*?)<\/pre><\/td>(.*?)<\/table><\/figure>/g, '
$4
'); 10 | }); -------------------------------------------------------------------------------- /scripts/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict'; 3 | hexo.on('generateBefore', () => { 4 | require('../lib/mergeConfig')(hexo); 5 | require('../lib/lazyload')(hexo); 6 | if (hexo.theme.config.minify.enable) { 7 | if (hexo.theme.config.minify.css) { 8 | require('../lib/minify/minifyCSS')(hexo); 9 | } 10 | // if (hexo.theme.config.minify.js) { 11 | // require('../lib/minify/minifyJS')(hexo); 12 | // } 13 | if (hexo.theme.config.minify.html) { 14 | require('../lib/minify/minifyHTML')(hexo); 15 | } 16 | } 17 | }); -------------------------------------------------------------------------------- /scripts/tag/note.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict'; 3 | hexo.extend.tag.register('note', (args, content) => { 4 | if(!args) { 5 | args = ['default']; 6 | } 7 | return `
${hexo.render.renderSync({ text: content, engine: 'markdown' }).split('\n').join('')}
`; 8 | }, { ends: true }); -------------------------------------------------------------------------------- /source/css/_base/color.styl: -------------------------------------------------------------------------------- 1 | // default color 2 | :root 3 | --text-color: $text-color 4 | --text-strong-color: $text-strong-color 5 | --text-light-color: $text-light-color 6 | --text-white-color: $text-white-color 7 | --divider-color: $divider-color 8 | --title-color: $title-color 9 | --link-color: $link-color 10 | --post-link-color: $post-link-color 11 | --link-hover-color: $link-hover-color 12 | --info-text-color: $info-text-color 13 | --widget-background-color: $widget-background-color 14 | --body-background-color: $body-background-color 15 | --badge-background-color: $badge-background-color 16 | --badge-hover-background-color: $badge-hover-background-color 17 | --border-color: $border-color 18 | --pre-color: $pre-color 19 | --tbody-background-color: $tbody-background-color 20 | --code-color: $code-color 21 | --code-background-color: $code-background-color 22 | --blue-tag-color: $blue-tag-color 23 | --blockquote-color: $blockquote-color 24 | --note-primary-border-color: $note-primary-border-color 25 | --note-primary-color: $note-primary-color 26 | --note-success-border-color: $note-success-border-color 27 | --note-success-color: $note-success-color 28 | --note-info-border-color: $note-info-border-color 29 | --note-info-color: $note-info-color 30 | --note-warning-border-color: $note-warning-border-color 31 | --note-warning-color: $note-warning-color 32 | --note-danger-border-color: $note-danger-border-color 33 | --note-danger-color: $note-danger-color 34 | --highlight-comment-color: $highlight-comment-color 35 | --highlight-tag-color: $highlight-tag-color 36 | --highlight-attr-color: $highlight-attr-color 37 | --highlight-literal-color: $highlight-literal-color 38 | --highlight-keyword-color: $highlight-keyword-color 39 | --highlight-string-color: $highlight-string-color 40 | --highlight-builtin-color: $highlight-builtin-color 41 | --base-shadow-color: $base-shadow-color 42 | --around-shadow-style: $around-shadow-style 43 | --tag-shadow-style: $tag-shadow-style 44 | --image-filter-style: $image-filter-style 45 | // dark-mode color 46 | dark-mode() 47 | --text-color: $dark-text-color 48 | --text-strong-color: $dark-text-strong-color 49 | --text-light-color: $dark-text-light-color 50 | --text-white-color: $dark-text-white-color 51 | --divider-color: $dark-divider-color 52 | --title-color: $dark-title-color 53 | --link-color: $dark-link-color 54 | --link-hover-color: $dark-link-hover-color 55 | --post-link-color: $dark-post-link-color 56 | --info-text-color: $dark-info-text-color 57 | --widget-background-color: $dark-widget-background-color 58 | --body-background-color: $dark-body-background-color 59 | --badge-background-color: $dark-badge-background-color 60 | --badge-hover-background-color: $dark-badge-hover-background-color 61 | --border-color: $dark-border-color 62 | --pre-color: $dark-pre-color 63 | --tbody-background-color: $dark-tbody-background-color 64 | --code-color: $dark-code-color 65 | --code-background-color: $dark-code-background-color 66 | --blue-tag-color: $dark-blue-tag-color 67 | --blockquote-color: $dark-blockquote-color 68 | --note-primary-border-color: $dark-note-primary-border-color 69 | --note-primary-color: $dark-note-primary-color 70 | --note-success-border-color: $dark-note-success-border-color 71 | --note-success-color: $dark-note-success-color 72 | --note-info-border-color: $dark-note-info-border-color 73 | --note-info-color: $dark-note-info-color 74 | --note-warning-border-color: $dark-note-warning-border-color 75 | --note-warning-color: $dark-note-warning-color 76 | --note-danger-border-color: $dark-note-danger-border-color 77 | --note-danger-color: $dark-note-danger-color 78 | --around-shadow-style: $dark-around-shadow-style 79 | --tag-shadow-style: $dark-tag-shadow-style 80 | --image-filter-style: $dark-image-filter-style 81 | @media (prefers-color-scheme: dark) 82 | :root:not([data-user-color-scheme]) 83 | dark-mode() 84 | [data-user-color-scheme='dark'] 85 | dark-mode() 86 | -------------------------------------------------------------------------------- /source/css/_base/highlight.styl: -------------------------------------------------------------------------------- 1 | code, pre 2 | font-family: 'Fira Code', 'Consolas', monospace !important 3 | code[class*='hljs'], pre[class*='highlight'], code[class*='language'] 4 | color: #ccc 5 | background: none 6 | // This !important is required to override the default style of highlight 7 | font-size: 1rem !important 8 | padding: 0 9 | margin-left: 0 10 | text-align: left 11 | white-space: pre 12 | word-spacing: normal 13 | word-break: normal 14 | word-wrap: normal 15 | line-height: 1.5 16 | -moz-tab-size: 4 17 | -o-tab-size: 4 18 | tab-size: 4 19 | -webkit-hyphens: none 20 | -ms-hyphens: none 21 | hyphens: none 22 | overflow-x: auto 23 | /* Code blocks */ 24 | pre[class*='highlight'] 25 | padding: 1em 26 | margin: 0.5em 0 27 | border-radius: 0.3rem 28 | overflow: auto 29 | white-space: pre 30 | overflow-wrap: normal 31 | &::-webkit-scrollbar 32 | display: none 33 | :not(pre) > code[class*='hljs'], pre[class*='highlight'] 34 | background: var(--pre-color) 35 | /* Inline code */ 36 | :not(pre) > code[class*='hljs'] 37 | padding: 0.1em 38 | border-radius: 0.3em 39 | white-space: normal 40 | .hljs-comment, .hljs-block-comment, .hljs-prolog, .hljs-doctype, .hljs-cdata 41 | color: var(--highlight-comment-color) 42 | .hljs-tag 43 | color: var(--highlight-tag-color) 44 | .hljs-title, .hljs-attr 45 | color: var(--highlight-attr-color) 46 | .hljs-boolean, .hljs-number, .hljs-literal 47 | color: var(--highlight-literal-color) 48 | .hljs-selector, .hljs-important, .hljs-atrule, .hljs-keyword 49 | color: var(--highlight-keyword-color) 50 | .hljs-string, .hljs-char, .hljs-attr-value, .hljs-regex, .hljs-variable 51 | color: var(--highlight-string-color) 52 | .hljs-operator, .hljs-entity, .hljs-url, .hljs-built_in 53 | color: var(--highlight-builtin-color) 54 | -------------------------------------------------------------------------------- /source/css/_base/index.styl: -------------------------------------------------------------------------------- 1 | @import 'reset' 2 | @import 'color' 3 | @import 'highlight' -------------------------------------------------------------------------------- /source/css/_base/reset.styl: -------------------------------------------------------------------------------- 1 | html, body, p, ol, ul, li, dl, dt, dd, blockquote, figure, fieldset, legend, textarea, pre, iframe, hr, h1, h2, h3, h4, h5, h6 2 | margin: 0 3 | padding: 0 4 | :root 5 | font-size: 15px 6 | h1, h2, h3, h4, h5, h6 7 | font-size: 100% 8 | font-weight: 500 9 | line-height: 1.25 10 | color: var(--title-color) 11 | h2 12 | font-size: 1.375rem 13 | margin-bottom: 0.5rem 14 | margin-top: 1.15rem 15 | h3 16 | font-size: 1.2rem 17 | margin-bottom: (2 / 3)rem 18 | margin-top: (4 / 3)rem 19 | h4 20 | font-size: 1.125rem 21 | margin-bottom: 0.8rem 22 | h5 23 | font-size: 1rem 24 | margin-bottom: 0.888rem 25 | h6 26 | font-size: 0.875rem 27 | color: var(--text-strong-color) 28 | ul 29 | list-style: none 30 | button, input, select, textarea 31 | margin: 0 32 | *, *::before, *::after 33 | box-sizing: inherit 34 | img 35 | border-style: none 36 | background-color: transparent 37 | img, video 38 | height: auto 39 | max-width: 100% 40 | iframe 41 | border: 0 42 | table 43 | border-collapse: collapse 44 | border-spacing: 0 45 | td, th 46 | padding: 0 47 | td:not([align]), th:not([align]) 48 | text-align: left 49 | a 50 | cursor: pointer 51 | color: var(--link-color) 52 | text-decoration: none 53 | .post-content a:not([data-nolink]) 54 | font-weight: 500 55 | cursor: pointer 56 | color: var(--text-strong-color) 57 | text-decoration: none 58 | border-bottom: 1px solid var(--post-link-color) 59 | transition: border-bottom 0.1s 60 | &:hover 61 | border-bottom: 2px solid var(--post-link-color) 62 | div 63 | display: block 64 | * 65 | box-sizing: border-box 66 | html, body 67 | height: 100vh 68 | font-size: $base-font-size 69 | font-family: $font-family 70 | color: var(--text-color) 71 | background-color: var(--body-background-color) 72 | box-sizing: border-box 73 | overflow-wrap: break-word 74 | ol ol, ul ol, ul ul 75 | margin-top: 0 76 | margin-bottom: 0 77 | ol ol, ul ol 78 | list-style-type: lower-roman 79 | ol ol ol, ol ul ol, ul ol ol, ul ul ol 80 | list-style-type: lower-alpha 81 | ol li, ul li 82 | margin-top: 0.5rem 83 | margin-bottom: 0.5rem 84 | li>p 85 | margin-top: 1rem 86 | li+li 87 | margin-top: 0.25rem 88 | code, kbd 89 | font-size: $sm-font-size 90 | color: var(--code-color) 91 | background-color: var(--code-background-color) 92 | padding: 0.25rem 0.4rem 93 | overflow-wrap: break-word 94 | word-wrap: break-word 95 | border-radius: 0.25rem 96 | vertical-align: 0.1rem 97 | code[class*=language-] 98 | margin: 0 99 | padding: 0 100 | border-radius: 0 101 | vertical-align: 0 102 | pre[class*=language-] 103 | border-radius: 0.3rem !important 104 | table 105 | display: block 106 | overflow: auto 107 | border-spacing: 0 108 | border-collapse: collapse 109 | tr 110 | background-color: var(--widget-background-color) 111 | td, th 112 | border: 0.08rem solid var(--border-color) 113 | padding: 0.5rem 0.75rem 114 | th 115 | font-weight: 700 116 | color: var(--title-color) 117 | tbody 118 | tr:nth-child(odd) 119 | background-color: var(--tbody-background-color) 120 | pre 121 | overflow: auto 122 | overflow-wrap: normal 123 | padding: 1rem 124 | border-radius: 0.3rem !important 125 | ::-webkit-scrollbar 126 | background-color: transparent 127 | width: 2px 128 | height: 3px 129 | background-clip: padding-box 130 | ::-webkit-scrollbar-thumb 131 | background-color: $divider-color 132 | border-radius: 0.3rem 133 | @media (max-width: 742px) 134 | #dark 135 | display: none 136 | #search 137 | display: none -------------------------------------------------------------------------------- /source/css/_mixins/index.styl: -------------------------------------------------------------------------------- 1 | theme-config(config, default) 2 | unquote(hexo-config(config) ? hexo-config(config) : default) -------------------------------------------------------------------------------- /source/css/_pages/about.styl: -------------------------------------------------------------------------------- 1 | .about-card 2 | display: flex 3 | flex-direction: row 4 | justify-content: center 5 | align-items: center 6 | .about-card-avatar 7 | width: 150px 8 | height: 150px 9 | margin-right: 90px 10 | .about-card-content 11 | display: flex 12 | flex-direction: column 13 | align-items: center 14 | justify-content: center 15 | .about-card-author 16 | margin-top: 12px 17 | font-size: $ex-font-size 18 | .about-card-dsc 19 | margin-top: 6px 20 | color: var(--text-light-color) 21 | .about-card-society 22 | margin-top: 8px 23 | display: flex 24 | flex-direction: row 25 | .about-card-society-icon 26 | padding: 0 5px 27 | .society-icon 28 | font-size: 22px 29 | color: var(--text-strong-color) 30 | 31 | @media (max-width: 862px) 32 | .about-card 33 | flex-direction: column 34 | .about-card-avatar 35 | margin-right: 0 -------------------------------------------------------------------------------- /source/css/_pages/archives.styl: -------------------------------------------------------------------------------- 1 | .archive-timeline-tag 2 | box-shadow: var(--tag-shadow-style) 3 | background-color: $blue-tag-color 4 | transition: background-color 0.3s 5 | border-radius: 0.3rem 6 | max-width: 66px 7 | height: 32px 8 | display: flex 9 | justify-content: center 10 | align-items: center 11 | color: var(--text-white-color) 12 | margin: 12px 0 13 | .archive-timeline-item 14 | position: relative 15 | margin-left: 12px 16 | .archive-timeline-post 17 | margin-left: 10px 18 | padding: 6px 6px 19 | .archive-timeline-post-content 20 | margin-top: 12px 21 | font-size: $ml-font-size 22 | .archive-timeline-post-item 23 | color: var(--text-font-color) 24 | @media(max-width: 862px) 25 | .archive-timeline-item 26 | margin-left: 18px 27 | .archive-timeline-post 28 | margin-left: 8px 29 | -------------------------------------------------------------------------------- /source/css/_pages/categories.styl: -------------------------------------------------------------------------------- 1 | .categories-page-title 2 | font-size: $ml-font-size 3 | .category-page-card 4 | margin-bottom: 24px 5 | .categories-page-card 6 | // overflow: hidden 7 | display: flex 8 | flex-wrap: wrap 9 | .categories-page-list-item 10 | width: (1 / 3) * 100% 11 | // float: left 12 | display: flex 13 | color: var(--text-color) 14 | font-size: $ml-font-size 15 | flex-direction: column 16 | align-items: center 17 | justify-content: center 18 | padding: 8px 20px 19 | &:hover 20 | cursor: pointer 21 | border-radius: 0.3rem 22 | background-color: var(--badge-background-color) 23 | transition: background-color 0.3s 24 | transition-duration: 0.3s 25 | transition-timing-function: ease-in-out 26 | + .categories-page-list-item 27 | margin-top: 0.4rem 28 | .categories-page-list-item-total 29 | font-size: $sm-font-size 30 | 31 | @media (max-width : 968px) 32 | .categories-page-list-item 33 | width: (1 / 2) * 100% 34 | 35 | @media (max-width : 742px) 36 | .categories-page-list-item 37 | width: 100% 38 | flex-direction: row 39 | justify-content: space-between 40 | align-content: center -------------------------------------------------------------------------------- /source/css/_pages/index.styl: -------------------------------------------------------------------------------- 1 | @import "widgets/*" 2 | @import "archives" 3 | @import "categories" 4 | @import "tags" 5 | @import "about" 6 | @import "rewrite" -------------------------------------------------------------------------------- /source/css/_pages/rewrite.styl: -------------------------------------------------------------------------------- 1 | .comment-card-title 2 | font-size: $ml-font-size 3 | margin-bottom: 16px 4 | .widget-title 5 | font-size: $lg-font-size 6 | font-weight: bold 7 | .token.operator, 8 | .token.entity, 9 | .token.url, 10 | .language-css .token.string, 11 | .style .token.string 12 | background: none !important -------------------------------------------------------------------------------- /source/css/_pages/tags.styl: -------------------------------------------------------------------------------- 1 | .tags-page-title 2 | font-size: $lg-font-size -------------------------------------------------------------------------------- /source/css/_pages/widgets/archive.styl: -------------------------------------------------------------------------------- 1 | .archive-card 2 | width: 100% 3 | .archive-card-header 4 | margin-bottom: 6px 5 | font-size: $base-font-size 6 | .iconfont 7 | font-size: $base-font-size 8 | .archive-card-list-item 9 | display: block 10 | color: var(--text-color) 11 | font-size: $md-font-size 12 | padding: 6px 8px 13 | transition: background-color 0.4s 14 | border-radius: 0.3rem 15 | &:hover 16 | // padding: 6px 12px 17 | cursor: pointer 18 | background-color: var(--badge-background-color) 19 | // transition: all 0.4s 20 | // transition-duration: 0.3s 21 | // transition-timing-function: ease-in-out 22 | // .archive-card-list-item-badge 23 | // background-color: var(--badge-hover-background-color) 24 | // transition: all 0.4s 25 | + .archive-card-list-item 26 | margin-top: 3px 27 | .archive-card-list-item-badge 28 | float: right 29 | margin-right: 10px 30 | font-size: $xs-font-size 31 | background-color: var(--badge-background-color) 32 | transition: all 0.4s 33 | padding: 2px 7px 34 | text-align: center 35 | border-radius: 0.3rem 36 | @media (max-width: 862px) 37 | .archive-widget 38 | display: $widgets-mobile -------------------------------------------------------------------------------- /source/css/_pages/widgets/author.styl: -------------------------------------------------------------------------------- 1 | .card-author 2 | margin-bottom: 1.5rem 3 | display: flex 4 | flex-direction: column 5 | align-items: center 6 | .author-img 7 | // width: 5.5rem 8 | // height: 5.5rem 9 | transition: all 0.5s 10 | .author-name 11 | margin-top: 0.7rem 12 | font-size: $ex-font-size 13 | .author-description 14 | margin-top: 0.5rem 15 | font-size: $md-font-size 16 | .author-message 17 | margin-top: 1.2rem 18 | width: 100% 19 | display: flex 20 | justify-content: center 21 | flex-direction: row 22 | > a 23 | padding: 0 16px 24 | color: var(--text-color) 25 | display: flex 26 | flex-direction: column 27 | align-items: center 28 | > span 29 | font-size: $lg-font-size 30 | + span 31 | font-size: $sm-font-size 32 | .author-card-society 33 | display: flex 34 | flex-direction: row 35 | justify-content: center 36 | align-items: center 37 | margin-top: 1rem 38 | .author-card-society-icon 39 | padding: 0 7px 40 | a 41 | color: var(--text-color) 42 | &:hover 43 | color: var(--link-hover-color) 44 | .iconfont 45 | font-size: $lg-font-size 46 | @media (max-width: 862px) 47 | .card-author 48 | display: $widgets-mobile 49 | margin-bottom: 0.8rem 50 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/button.styl: -------------------------------------------------------------------------------- 1 | .basebutton 2 | display: flex 3 | cursor: pointer 4 | position: fixed 5 | width: 44px 6 | height: 44px 7 | border-radius: 50% 8 | box-shadow: var(--around-shadow-style) 9 | justify-content: center 10 | align-items: center 11 | background-color: var(--widget-background-color) 12 | transition: all 0.3s 13 | #scrollbutton 14 | transform: rotate(90deg) 15 | display: flex 16 | opacity: 0 17 | bottom: 32px 18 | right: 32px 19 | .button-icon 20 | font-size: $md-font-size 21 | font-weight: bold 22 | #menubutton 23 | display: flex 24 | opacity: 0 25 | bottom: 32px 26 | right: 32px 27 | .button-icon 28 | font-size: $ml-font-size 29 | font-weight: bold 30 | #popbutton 31 | z-index: 10 32 | bottom: 32px 33 | right: 32px 34 | .button-icon 35 | font-size: $sm-font-size 36 | font-weight: bold 37 | #darkbutton 38 | display: flex 39 | opacity: 0 40 | bottom: 32px 41 | right: 32px 42 | .button-icon 43 | font-size: $md-font-size 44 | #searchbutton 45 | display: flex 46 | opacity: 0 47 | bottom: 32px 48 | right: 32px 49 | .button-icon 50 | font-size: $md-font-size 51 | .postbutton 52 | cursor: pointer 53 | background-color: var(--link-color) 54 | border-radius: 4px 55 | font-size: $md-font-size 56 | padding: 4px 10px 57 | border: none 58 | color: #fff 59 | &:hover 60 | background-color: var(--link-hover-color) 61 | &:focus 62 | outline: none 63 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/card.styl: -------------------------------------------------------------------------------- 1 | .card 2 | border-radius: $border-radius 3 | background-color: var(--widget-background-color) 4 | max-width: 100% 5 | box-shadow: var(--around-shadow-style) 6 | transition: background-color 0.3s 7 | .image-wrapper+.card // if post has banner, the post-card border-top-radius will be 0 8 | border-radius: 0 0 $border-radius $border-radius 9 | .card +.card, .card +.archive-timeline 10 | margin-top: 1.5rem 11 | // content style 12 | .card-content, .card-author 13 | background-color: var(--widget-background-color) 14 | transition: background-color 0.3s 15 | padding: 1.5rem 16 | .post-title, .card-excerpt 17 | margin-bottom: 0.8rem 18 | .post-title 19 | font-size: 1.4rem 20 | font-weight: 400 21 | padding-bottom: 0.4rem 22 | color: var(--title-color) 23 | line-height: 1.125 24 | .card-post-footer 25 | display: flex 26 | justify-content: space-between 27 | padding: 0 28 | a:hover 29 | color: var(--link-hover-color) 30 | .post-meta, .post-meta-link 31 | color: var(--text-light-color) 32 | padding: 0 2px 33 | .dot 34 | &::after 35 | content: '·' 36 | @media (max-width: 862px) 37 | .card +.card 38 | margin-top: 0.8rem 39 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/categories.styl: -------------------------------------------------------------------------------- 1 | .categories-card 2 | width: 100% 3 | .categories-header 4 | margin-bottom: 6px 5 | font-size: $base-font-size 6 | .iconfont 7 | font-size: $base-font-size 8 | .categories-list-item 9 | color: var(--text-color) 10 | padding: 6px 8px 11 | font-size: $md-font-size 12 | border-radius: $border-radius 13 | transition: background-color 0.4s ease-in-out 14 | &:hover 15 | // padding: 6px 12px 16 | cursor: pointer 17 | // border-radius: $border-radius 18 | background-color: var(--badge-background-color) 19 | // transition: background-color 0.4s ease-in-out 20 | // transition: all 0.4s 21 | // transition-duration: 0.4s 22 | // transition-timing-function: ease-in-out 23 | // .categories-list-item-badge 24 | // background-color: var(--badge-hover-background-color) 25 | // transition: all 0.4s 26 | + .categories-list-item 27 | margin-top: 3px 28 | .categories-list-item-badge 29 | float: right 30 | margin-right: 10px 31 | font-size: $xs-font-size 32 | background-color: var(--badge-background-color) 33 | // transition: all 0.4s 34 | padding: 2px 7px 35 | text-align: center 36 | border-radius: $xs-border-radius 37 | 38 | @media (max-width: 862px) 39 | .categories-widget 40 | display: $widgets-mobile 41 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/columns.styl: -------------------------------------------------------------------------------- 1 | @import 'postlist.styl' 2 | 3 | // layout into two columns 4 | .columns, .left-column, .main-column, .right-column 5 | display: block 6 | padding: 0.5rem 0.25rem 7 | .left-column 8 | .sticky-tablet > div 9 | margin-bottom: 0.8rem 10 | .main-column 11 | content-visibility: auto 12 | .right-column, .left-column 13 | display: none 14 | @media screen and (min-width: 862px) 15 | .columns 16 | display: flex 17 | .left-column, .right-column 18 | width: (1 / 3) * 100% 19 | // .left-column 20 | // order: 1 21 | .main-column 22 | // order: 2 23 | width: (2 / 3) * 100% 24 | // big screen layout, layout into three columns 25 | @media screen and (min-width: 1280px) 26 | .left-column .display-when-two-columns, .widescreen-archive 27 | display: none 28 | .main-column 29 | width: 52% 30 | .left-column, .right-column 31 | width: 24% 32 | .right-column, .left-column 33 | // order: 3 34 | display: block 35 | // sticky aside 36 | @media screen and (min-width: 1280px) 37 | .sticky-widescreen 38 | position: -webkit-sticky 39 | position: sticky 40 | top: 1.5rem 41 | @media screen and (min-width: 862px) 42 | .columns, .left-column, .main-column, .right-column 43 | padding: 0.75rem 44 | .sticky-tablet 45 | position: -webkit-sticky 46 | position: sticky 47 | top: 1.5rem 48 | .left-column 49 | .sticky-tablet > div 50 | margin-bottom: 1.5rem 51 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/container.styl: -------------------------------------------------------------------------------- 1 | .container, .footer-container, .navbar-container 2 | flex-grow: 1 3 | width: 100% 4 | margin: 0 auto 5 | @media screen and (min-width: 1088px) 6 | .footer-container 7 | max-width: 992px 8 | @media screen and (min-width: 1280px) 9 | .footer-container 10 | max-width: 1184px 11 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/footer.styl: -------------------------------------------------------------------------------- 1 | // default footer 2 | .footer 3 | font-size: $sm-font-size 4 | background-color: var(--widget-background-color) 5 | transition: background-color 0.3s 6 | width: 100% 7 | box-shadow: var(--around-shadow-style) 8 | padding: 1.5rem 1rem 1.5rem 9 | bottom: 0 10 | .footer-container 11 | color: var(--info-text-color) 12 | display: block 13 | justify-content: space-between 14 | a 15 | color: var(--text-strong-color) 16 | &:hover 17 | color: var(--link-hover-color) 18 | .footer-dsc 19 | margin-bottom: 6px 20 | display: flex 21 | justify-content: center 22 | align-items: center 23 | .BbeiAn-info 24 | display: flex 25 | justify-content: center -------------------------------------------------------------------------------- /source/css/_pages/widgets/friends.styl: -------------------------------------------------------------------------------- 1 | .friend-card 2 | overflow: hidden 3 | .friend-links 4 | display: flex 5 | flex-wrap: wrap 6 | .friend-item 7 | width: (1 / 3) * 100% 8 | padding: 6px 12px 9 | // float: left 10 | margin: 8px 0 11 | border-radius: $border-radius 12 | &:hover 13 | background-color: var(--badge-background-color) 14 | transition: background-color 0.3s 15 | transition-duration: 0.3s 16 | transition-timing-function: ease-in-out 17 | .friend-item-card 18 | display: block 19 | width: 100% 20 | height: 100% 21 | .friend-item-content 22 | display: flex 23 | align-items: center 24 | .friend-text 25 | width: 100% - 44px 26 | display: flex 27 | flex-direction: column 28 | .friend-name 29 | max-width: 100% 30 | overflow: hidden 31 | text-overflow: ellipsis 32 | white-space: nowrap 33 | color: var(--text-strong-color) 34 | font-size: $ml-font-size 35 | max-height: 24.8px 36 | .friend-dsc 37 | max-width: 100% 38 | overflow: hidden 39 | text-overflow: ellipsis 40 | white-space: nowrap 41 | color: var(--info-text-color) 42 | font-size: $sm-font-size 43 | max-height: 19.2px 44 | .friend-avatar 45 | height: 44px 46 | width: 44px 47 | margin-right: 14px 48 | @media (max-width: 968px) 49 | .friend-item 50 | width: (1 / 2) * 100% 51 | @media (max-width: 742px) 52 | .friend-item 53 | width: 100% 54 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/nav.styl: -------------------------------------------------------------------------------- 1 | // default navbar 2 | .navbar 3 | background-color: var(--widget-background-color) 4 | transition: background-color 0.3s 5 | height: 3.5rem 6 | box-shadow: var(--around-shadow-style) 7 | display: flex 8 | align-items: stretch 9 | .navbar-logo 10 | display: inline-block 11 | margin-left: 96px 12 | .navbar-logo-main 13 | display: inline-flex 14 | height: 100% 15 | align-items: center 16 | justify-content: space-around 17 | padding: 0.7rem 0.6rem 18 | color: var(--text-color) 19 | .navbar-logo-dsc 20 | font-size: $lg-font-size 21 | .navbar-logo-img 22 | // height: 34px 23 | // width: 34px 24 | margin-right: 10px 25 | .navbar-menu 26 | font-size: $md-font-size 27 | display: flex 28 | align-items: center 29 | a 30 | display: inline-flex 31 | height: 100% 32 | align-items: center 33 | color: var(--text-color) 34 | cursor: pointer 35 | padding: 0.7rem 0.6rem 36 | &:hover 37 | color: var(--link-hover-color) 38 | &-btn 39 | background: none 40 | border: none 41 | display: flex 42 | align-items: center 43 | color: var(--text-color) 44 | &:hover 45 | cursor: pointer 46 | // mobiles navbar 47 | @media (max-width: 1088px) 48 | .navbar 49 | min-height: 90px 50 | display: block 51 | .navbar-logo 52 | margin-left: 0 53 | display: block 54 | .navbar-logo-main 55 | display: flex 56 | justify-content: center 57 | .navbar-menu 58 | width: 100% 59 | display: flex 60 | margin-right: 0 61 | justify-content: center 62 | @media (max-width: 586px) 63 | .navbar-menu 64 | display: flex 65 | justify-content: space-evenly -------------------------------------------------------------------------------- /source/css/_pages/widgets/pagination.styl: -------------------------------------------------------------------------------- 1 | .nav 2 | display: flex 3 | flex-direction: row 4 | margin-top: 1.5rem 5 | .nav-item-prev, .nav-item-next 6 | display: flex 7 | flex: 50% 8 | .nav-next-icon 9 | margin-left: 0.7rem 10 | .nav-prev-icon 11 | margin-right: 0.7rem 12 | .nav-item-prev 13 | justify-content: flex-start 14 | text-align: left 15 | .nav-item-next 16 | justify-content: flex-end 17 | text-align: right 18 | .nav-link 19 | display: flex 20 | flex-direction: row 21 | align-items: center 22 | padding: 0 0.5rem 23 | .nav-prev-icon, .nav-next-icon 24 | color: var(--text-light-color) 25 | width: 0.65rem 26 | .nav-label 27 | font-size: 0.9rem 28 | font-weight: 500 29 | line-height: 1.6rem 30 | color: var(--text-light-color) 31 | .nav-title 32 | font-size: 1rem 33 | font-weight: 500 34 | line-height: 1.2rem 35 | color: var(--text-color) -------------------------------------------------------------------------------- /source/css/_pages/widgets/post.styl: -------------------------------------------------------------------------------- 1 | .post-show-meta 2 | margin-bottom: 1rem 3 | .post-content 4 | dl, ol, ul, blockquote, h6, figure, pre, p, table 5 | + * 6 | margin-top: 1em 7 | p 8 | line-height: 1.8rem 9 | blockquote 10 | margin-top: 1rem 11 | padding: 1rem 12 | background-color: var(--blockquote-color) 13 | transition: background-color 0.3s 14 | border-left: 0.25rem solid var(--border-color) 15 | p 16 | margin-bottom: 0 17 | ul 18 | list-style: disc 19 | margin-left: 1.2em 20 | ol 21 | list-style-position: outside 22 | margin-left: 1.2em 23 | margin-top: 0 24 | ol:not([type]) 25 | list-style-type: decimal 26 | h1, h2 27 | padding-bottom: 0.35rem 28 | border-bottom: 1px solid var(--border-color) 29 | .katex-block 30 | overflow-x: auto 31 | mjx-container 32 | overflow-x: auto 33 | overflow-y: hidden 34 | &:focus, svg:focus 35 | outline: none 36 | /* post tags */ 37 | .post-note 38 | margin-top: 1rem 39 | margin-bottom: 1rem 40 | padding: 1rem 41 | border-radius: 0.2rem 42 | border-left-width: 0.25rem 43 | border-left-style: solid 44 | p 45 | margin-bottom: 0 46 | .copyright 47 | a 48 | color: var(--text-color) 49 | font-weight: bold 50 | p 51 | + p 52 | margin-top: 8px 53 | .note-default 54 | background-color: var(--blockquote-color) 55 | border-left-color: var(--border-color) 56 | transition: background-color 0.3s 57 | .note-primary 58 | border-left-color: var(--note-primary-border-color) 59 | background-color: var(--note-primary-color) 60 | transition: background-color 0.3s 61 | .note-success 62 | border-left-color: var(--note-success-border-color) 63 | background-color: var(--note-success-color) 64 | transition: background-color 0.3s 65 | .note-info 66 | border-left-color: var(--note-info-border-color) 67 | background-color: var(--note-info-color) 68 | transition: background-color 0.3s 69 | .note-warning 70 | border-left-color: var(--note-warning-border-color) 71 | background-color: var(--note-warning-color) 72 | transition: background-color 0.3s 73 | .note-danger 74 | border-left-color: var(--note-danger-border-color) 75 | background-color: var(--note-danger-color) 76 | transition: background-color 0.3s 77 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/postlist.styl: -------------------------------------------------------------------------------- 1 | .image-wrapper 2 | overflow: hidden 3 | display: block 4 | width: 100% 5 | height: 0 6 | position: relative 7 | background-color: var(--widget-background-color) 8 | border-radius: 0.5rem 0.5rem 0 0 9 | .image 10 | -o-object-fit: cover 11 | object-fit: cover 12 | width: 100% 13 | -webkit-filter: var(--image-filter-style) 14 | filter: var(--image-filter-style) 15 | position: absolute 16 | transition: -webkit-filter 0.4s ease 0s 17 | transition: filter 0.4s ease 0s 18 | transition: filter 0.4s ease 0s, -webkit-filter 0.4s ease 0s 19 | &:not(.loaded) 20 | -webkit-filter: blur(5px) var(--image-filter-style) 21 | filter: blur(5px) var(--image-filter-style) 22 | .post-image 23 | margin: auto 24 | -webkit-filter: var(--image-filter-style) 25 | filter: var(--image-filter-style) 26 | transition: -webkit-filter 0.4s ease 0s 27 | transition: filter 0.4s ease 0s 28 | transition: filter 0.4s ease 0s, -webkit-filter 0.4s ease 0s 29 | &:not(.loaded) 30 | -webkit-filter: blur(5px) 31 | filter: blur(5px) 32 | @media screen and (min-width: 768px) 33 | .image-wrapper 34 | padding-bottom: 300px 35 | .image 36 | height: 300px 37 | @media screen and (max-width: 767px) 38 | .image-wrapper 39 | height: 16.48rem 40 | .image 41 | height: 16.48rem -------------------------------------------------------------------------------- /source/css/_pages/widgets/recentposts.styl: -------------------------------------------------------------------------------- 1 | .recent-posts-header 2 | margin-bottom: 16px 3 | font-size: $base-font-size 4 | .iconfont 5 | font-size: $base-font-size 6 | .recent-posts-item 7 | padding-left: 6px 8 | &:last-child .divider 9 | display: none 10 | + .recent-posts-item 11 | margin-top: 10px 12 | .recent-posts-item-title 13 | font-size: $sm-font-size 14 | .recent-posts-item-content 15 | color: var(--text-color) 16 | margin-top: 6px 17 | font-size: $md-font-size 18 | padding: 6px 0 19 | padding-left: 8px 20 | transition: background-color .4s ease-in-out 21 | border-radius: $border-radius 22 | &:hover 23 | // padding-left: 16px 24 | cursor: pointer 25 | background-color: var(--badge-background-color) 26 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/search.styl: -------------------------------------------------------------------------------- 1 | #search 2 | font-weight: bold 3 | #search-input 4 | background-color: var(--widget-background-color) 5 | margin-top: 12px 6 | z-index: 20 7 | position: fixed 8 | left: 10% 9 | width: 80% 10 | height: 44px 11 | padding: 8px 12px 12 | border-radius: $border-radius 13 | border: 1px solid var(--divider-color) 14 | color: var(--text-color) 15 | font-size: 14px 16 | &:focus 17 | outline: none 18 | #search-content 19 | max-height: 800px 20 | overflow: auto 21 | position: fixed 22 | z-index: 20 23 | margin-top: 64px 24 | left: 10% 25 | width: 80% 26 | .local-search-empty 27 | color: var(--info-text-color) 28 | line-height: 44px 29 | text-align: center 30 | display: block 31 | ul 32 | overflow-y: auto 33 | border: 1px solid var(--divider-color) 34 | padding: 10px 20px 35 | background: var(--widget-background-color) 36 | box-shadow: 1px 2px 4px var(--divider-color) 37 | li 38 | text-align: left 39 | border-bottom: 1px solid var(--divider-color) 40 | padding-bottom: 20px 41 | margin-bottom: 20px 42 | line-height: 30px 43 | font-weight: normal 44 | &:last-child 45 | border-bottom: none 46 | margin-bottom: 0 47 | a 48 | margin-top: 20px 49 | font-size: $md-font-size 50 | p 51 | margin-top: 10px 52 | font-size: 14px 53 | max-height: 124px 54 | overflow: hidden 55 | .search-keyword 56 | color: var(--note-danger-border-color) 57 | font-style: normal -------------------------------------------------------------------------------- /source/css/_pages/widgets/section.styl: -------------------------------------------------------------------------------- 1 | .section-wrap 2 | display: flex 3 | justify-content: center 4 | padding: 1.3rem 1rem 5 | .wrapper 6 | min-height: 100% 7 | @media (max-width: 862px) 8 | .section-wrap 9 | padding: .8rem .4rem -------------------------------------------------------------------------------- /source/css/_pages/widgets/tags.styl: -------------------------------------------------------------------------------- 1 | .categories-card 2 | width: 100% 3 | .tags-header 4 | margin-bottom: 12px 5 | font-size: $base-font-size 6 | .iconfont 7 | font-size: $base-font-size 8 | .tags-list 9 | overflow: hidden 10 | .tags-list-item 11 | height: 28px 12 | display: flex 13 | flex-direction: row 14 | align-items: center 15 | color: var(--text-color) 16 | float: left 17 | margin: 3px 6px; 18 | font-size: $md-font-size 19 | background-color: var(--badge-background-color) 20 | transition: background-color 0.3s 21 | padding: 3px 7px 22 | text-align: center 23 | border-radius: $border-radius 24 | &:hover 25 | cursor: pointer 26 | background-color: var(--badge-hover-background-color) 27 | transition: background-color 0.3s 28 | .tag-page-card 29 | margin-bottom: 24px 30 | @media (max-width: 862px) 31 | .tags-widget 32 | display: $widgets-mobile 33 | -------------------------------------------------------------------------------- /source/css/_pages/widgets/toc.styl: -------------------------------------------------------------------------------- 1 | .toc-card 2 | margin-bottom: 1.5rem 3 | .toc-header 4 | margin-bottom: 6px 5 | font-size: $base-font-size 6 | .iconfont 7 | font-size: $ml-font-size 8 | .toc 9 | overflow: auto 10 | max-height: calc(100vh - 30rem) 11 | padding-right: 1rem 12 | ol, li 13 | list-style-type: none 14 | a 15 | color: var(--text-color) 16 | display: block 17 | padding: 0.3rem 0.65rem 18 | border-radius: $border-radius 19 | &:hover 20 | background-color: var(--badge-background-color) 21 | transition: background-color 0.3s 22 | .toc-child 23 | margin-left: 0.8rem 24 | position: relative 25 | &::before 26 | content: '' 27 | position: absolute 28 | top: 0 29 | width: 1px 30 | background-color: var(--badge-background-color) 31 | transition: background-color 0.3s 32 | height: 100% 33 | > li 34 | margin-left: 0.7rem 35 | .toc-item 36 | margin-bottom: 0 37 | margin-top: 0 38 | #mobiletoc 39 | display: none 40 | #mask 41 | position: fixed 42 | left: 0 43 | right: 0 44 | top: 0 45 | bottom: 0 46 | background-color: #000000 47 | opacity: 0.6 48 | @media (max-width: 862px) 49 | .toc-card 50 | display: none 51 | position: fixed 52 | bottom: 0 53 | left: 0 54 | right: 0 55 | margin: 0.8rem 1.2rem 56 | z-index: 20 -------------------------------------------------------------------------------- /source/css/_variables/index.styl: -------------------------------------------------------------------------------- 1 | // color variables 2 | $text-color = theme-config('color.text-color', '#3c4858') 3 | $text-strong-color = theme-config('color.text-strong-color', '#2f3d4e') 4 | $text-light-color = theme-config('color.text-light-color', '#60656a') 5 | $text-white-color = theme-config('color.text-white-color', '#fff') 6 | $divider-color = theme-config('color.divider-color', '#e6e8ee') 7 | $title-color = theme-config('color.title-color', '#475b6d') 8 | $link-color = theme-config('color.link-color', '#3273dc') 9 | $link-hover-color = theme-config('color.link-hover-color', '#6596e5') 10 | $post-link-color = theme-config('color.post-link-color', '#d71a1b') 11 | $info-text-color = theme-config('color.info-text-color', '#60656a') 12 | $widget-background-color = theme-config('color.widget-background-color', '#fff') 13 | $body-background-color = theme-config('color.body-background-color', '#f2f5f8') 14 | $badge-background-color = theme-config('color.badge-background-color', '#edeff3') 15 | $badge-hover-background-color = theme-config('color.badge-background-color', '#adb7d0') 16 | $border-color = theme-config('color.border-color', '#e1e4e9') 17 | $pre-color = theme-config('color.pre-color', '#2d2d2d') 18 | $tbody-background-color = theme-config('color.tbody-background-color', '#f4f5f7') 19 | $code-color = theme-config('color.code-color', '#50687c') 20 | $code-background-color = theme-config('color.code-background-color', '#e9eaf0') 21 | $blockquote-color = theme-config('color.blockquote-color', '#f9f8f7') 22 | /* tags color */ 23 | $blue-tag-color = theme-config('color.blue-tag-color', '#3273dc') 24 | /* note color */ 25 | $note-primary-border-color = theme-config('color.note-primary-border-color', '#428bca') 26 | $note-primary-color = theme-config('color.note-primary-color', '#daf3fc') 27 | $note-success-border-color = theme-config('color.note-success-border-color', '#5cb85c') 28 | $note-success-color = theme-config('color.note-success-color', '#ebfbe2') 29 | $note-info-border-color = theme-config('color.note-info-border-color', '#5bc0de') 30 | $note-info-color = theme-config('color.note-info-color', '#dffdfb') 31 | $note-warning-border-color = theme-config('color.note-warning-border-color', '#f0ad30') 32 | $note-warning-color = theme-config('color.note-warning-color', '#fef5d5') 33 | $note-danger-border-color = theme-config('color.note-danger-border-color', '#d9534f') 34 | $note-danger-color = theme-config('color.note-danger-color', '#fde8dc') 35 | /* code highlight color */ 36 | $highlight-comment-color = theme-config('color.highlight-comment-color', '#999') 37 | $highlight-tag-color = theme-config('color.highlight-tag-color', '#e2777a') 38 | $highlight-attr-color = theme-config('color.highlight-attr-color', '#6196cc') 39 | $highlight-literal-color = theme-config('color.highlight-literal-color', '#f08d49') 40 | $highlight-keyword-color = theme-config('color.highlight-keyword-color', '#cc99cd') 41 | $highlight-string-color = theme-config('color.highlight-string-color', '#7ec699') 42 | $highlight-builtin-color = theme-config('color.highlight-builtin-color', '#67cdcc') 43 | // dark mode color 44 | $dark-text-color = theme-config('color.dark-text-color', '#c4c6c9') 45 | $dark-text-strong-color = theme-config('color.dark-text-strong-color', '#fff') 46 | $dark-text-light-color = theme-config('color.dark-text-light-color', '#909faf') 47 | $dark-text-white-color = theme-config('color.dark-text-white-color', '#fff') 48 | $dark-divider-color = theme-config('color.dark-divider-color', '#a09c9c') 49 | $dark-title-color = theme-config('color.dark-title-color', '#c4c6c9') 50 | $dark-link-color = theme-config('color.dark-link-color', '#74a9ff') 51 | $dark-link-hover-color = theme-config('color.dark-link-hover-color', '#6596e5') 52 | $dark-post-link-color = theme-config('color.dark-post-link-color', '#d71a1b') 53 | $dark-info-text-color = theme-config('color.dark-info-text-color', '#909faf') 54 | $dark-widget-background-color = theme-config('color.dark-widget-background-color', '#1c1c1e') 55 | $dark-body-background-color = theme-config('color.dark-body-background-color', '#0d0d0d') 56 | $dark-badge-background-color = theme-config('color.dark-badge-background-color', '#485061') 57 | $dark-badge-hover-background-color = theme-config('color.dark-badge-background-color', '#818CA0') 58 | $dark-border-color = theme-config('color.dark-border-color', '#435266') 59 | $dark-pre-color = theme-config('color.dark-pre-color', '#3c495b') 60 | $dark-tbody-background-color = theme-config('color.dark-tbody-background-color', '#3c495b') 61 | $dark-code-color = theme-config('color.dark-code-color', '#c3c7cb') 62 | $dark-code-background-color = theme-config('color.dark-code-background-color', '#3e4b5e') 63 | $dark-blockquote-color = theme-config('color.dark-blockquote-color', '#181c27') 64 | /* note color */ 65 | $dark-note-primary-border-color = theme-config('color.dark-note-primary-border-color', '#0c2760') 66 | $dark-note-primary-color = theme-config('color.dark-note-primary-color', '#456d92') 67 | $dark-note-success-border-color = theme-config('color.dark-note-success-border-color', '#11582a') 68 | $dark-note-success-color = theme-config('color.dark-note-success-color', '#549148') 69 | $dark-note-info-border-color = theme-config('color.dark-note-info-border-color', '#113c6a') 70 | $dark-note-info-color = theme-config('color.dark-note-info-color', '#2a6279') 71 | $dark-note-warning-border-color = theme-config('color.dark-note-warning-border-color', '#733f09') 72 | $dark-note-warning-color = theme-config('color.dark-note-warning-color', '#937c43') 73 | $dark-note-danger-border-color = theme-config('color.dark-note-danger-border-color', '#680f2a') 74 | $dark-note-danger-color = theme-config('color.dark-note-danger-color', '#925346') 75 | // font variables 76 | $base-font-size = theme-config('font.font-size', '16px') 77 | $font-family = theme-config('font.font-family', 'Microsoft Yahei, sans-serif') 78 | $xs-font-size = 0.8rem 79 | $sm-font-size = 0.9rem 80 | $md-font-size = 1rem 81 | $ml-font-size = 1.15rem 82 | $lg-font-size = 1.3rem 83 | $ex-font-size = 1.5rem 84 | // style variables 85 | $base-shadow-color = 0deg, 0%, 72% 86 | $around-shadow-style = .3px .2px .3px hsla($base-shadow-color, 0.4), .7px .5px .8px -1.3px hsla($base-shadow-color, 0.32), 1.9px 1.4px 2.1px -2.7px hsla($base-shadow-color, 0.25), 5.2px 3.8px 5.8px -4px hsla($base-shadow-color, 0.17) 87 | $tag-shadow-style = 0 2px 4px 0 rgba(0, 0, 0, 0.2) 88 | $image-filter-style = none 89 | $dark-around-shadow-style = none 90 | $dark-tag-shadow-style = none 91 | $dark-image-filter-style = brightness(0.6) contrast(1.2) 92 | $border-radius = theme-config('border.border-radius', '.5rem') 93 | $xs-border-radius = theme-config('border.border-radius-lg', '.2rem') 94 | // config styles 95 | $widgets-mobile = theme-config('widgets.showWidgetsMobiles', 'none') -------------------------------------------------------------------------------- /source/css/main.styl: -------------------------------------------------------------------------------- 1 | @import "_mixins/index" 2 | @import "_variables/index" 3 | @import "_base/index" 4 | @import "_pages/index" -------------------------------------------------------------------------------- /source/js/lib/busuanzi.min.js: -------------------------------------------------------------------------------- 1 | var bszCaller,bszTag;!function(){var c,d,e,a=!1,b=[];ready=function(c){return a||"interactive"===document.readyState||"complete"===document.readyState?c.call(document):b.push(function(){return c.call(this)}),this},d=function(){for(var a=0,c=b.length;c>a;a++)b[a].apply(document);b=[]},e=function(){a||(a=!0,d.call(window),document.removeEventListener?document.removeEventListener("DOMContentLoaded",e,!1):document.attachEvent&&(document.detachEvent("onreadystatechange",e),window==window.top&&(clearInterval(c),c=null)))},document.addEventListener?document.addEventListener("DOMContentLoaded",e,!1):document.attachEvent&&(document.attachEvent("onreadystatechange",function(){/loaded|complete/.test(document.readyState)&&e()}),window==window.top&&(c=setInterval(function(){try{a||document.documentElement.doScroll("left")}catch(b){return}e()},5)))}(),bszCaller={fetch:function(a,b){var c="BusuanziCallback_"+Math.floor(1099511627776*Math.random());window[c]=this.evalCall(b),a=a.replace("=BusuanziCallback","="+c),scriptTag=document.createElement("SCRIPT"),scriptTag.type="text/javascript",scriptTag.defer=!0,scriptTag.src=a,document.getElementsByTagName("HEAD")[0].appendChild(scriptTag)},evalCall:function(a){return function(b){ready(function(){try{a(b),scriptTag.parentElement.removeChild(scriptTag)}catch(c){bszTag.hides()}})}}},bszCaller.fetch("//busuanzi.ibruce.info/busuanzi?jsonpCallback=BusuanziCallback",function(a){bszTag.texts(a),bszTag.shows()}),bszTag={bszs:["site_pv","page_pv","site_uv"],texts:function(a){this.bszs.map(function(b){var c=document.getElementById("busuanzi_value_"+b);c&&(c.innerHTML=a[b])})},hides:function(){this.bszs.map(function(a){var b=document.getElementById("busuanzi_container_"+a);b&&(b.style.display="none")})},shows:function(){this.bszs.map(function(a){var b=document.getElementById("busuanzi_container_"+a);b&&(b.style.display="inline")})}}; -------------------------------------------------------------------------------- /source/js/lib/lightbox/baguetteBox.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * baguetteBox.js 3 | * @author feimosi 4 | * @version 1.11.1 5 | * @url https://github.com/feimosi/baguetteBox.js 6 | */#baguetteBox-overlay{display:none;opacity:0;position:fixed;overflow:hidden;top:0;left:0;width:100%;height:100%;z-index:1000000;background-color:#222;background-color:rgba(0,0,0,.8);-webkit-transition:opacity .5s ease;transition:opacity .5s ease}#baguetteBox-overlay.visible{opacity:1}#baguetteBox-overlay .full-image{display:inline-block;position:relative;width:100%;height:100%;text-align:center}#baguetteBox-overlay .full-image figure{display:inline;margin:0;}#baguetteBox-overlay .full-image img{display:inline-block;width:auto;height:auto;max-height:100%;max-width:100%;vertical-align:middle;-webkit-box-shadow:0 0 8px rgba(0,0,0,.6);-moz-box-shadow:0 0 8px rgba(0,0,0,.6);box-shadow:0 0 8px rgba(0,0,0,.6)}#baguetteBox-overlay .full-image figcaption{display:block;position:absolute;bottom:0;width:100%;text-align:center;line-height:1.8;white-space:normal;color:#ccc;background-color:#000;background-color:rgba(0,0,0,.6);font-family:sans-serif}#baguetteBox-overlay .full-image:before{content:"";display:inline-block;height:50%;width:1px;margin-right:-1px}#baguetteBox-slider{position:absolute;left:0;top:0;height:100%;width:100%;white-space:nowrap;-webkit-transition:left .4s ease,-webkit-transform .4s ease;transition:left .4s ease,-webkit-transform .4s ease;transition:left .4s ease,transform .4s ease;transition:left .4s ease,transform .4s ease,-webkit-transform .4s ease,-moz-transform .4s ease}#baguetteBox-slider.bounce-from-right{-webkit-animation:bounceFromRight .4s ease-out;animation:bounceFromRight .4s ease-out}#baguetteBox-slider.bounce-from-left{-webkit-animation:bounceFromLeft .4s ease-out;animation:bounceFromLeft .4s ease-out}@-webkit-keyframes bounceFromRight{0%,100%{margin-left:0}50%{margin-left:-30px}}@keyframes bounceFromRight{0%,100%{margin-left:0}50%{margin-left:-30px}}@-webkit-keyframes bounceFromLeft{0%,100%{margin-left:0}50%{margin-left:30px}}@keyframes bounceFromLeft{0%,100%{margin-left:0}50%{margin-left:30px}}.baguetteBox-button#next-button,.baguetteBox-button#previous-button{top:50%;top:calc(50% - 30px);width:44px;height:60px}.baguetteBox-button{position:absolute;cursor:pointer;outline:0;padding:0;margin:0;border:0;-moz-border-radius:15%;border-radius:15%;background-color:#323232;background-color:rgba(50,50,50,.5);color:#ddd;font:1.6em sans-serif;-webkit-transition:background-color .4s ease;transition:background-color .4s ease}.baguetteBox-button:focus,.baguetteBox-button:hover{background-color:rgba(50,50,50,.9)}.baguetteBox-button#next-button{right:2%}.baguetteBox-button#previous-button{left:2%}.baguetteBox-button#close-button{top:20px;right:2%;right:calc(2% + 6px);width:30px;height:30px}.baguetteBox-button svg{position:absolute;left:0;top:0}.baguetteBox-spinner{width:40px;height:40px;display:inline-block;position:absolute;top:50%;left:50%;margin-top:-20px;margin-left:-20px}.baguetteBox-double-bounce1,.baguetteBox-double-bounce2{width:100%;height:100%;-moz-border-radius:50%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:bounce 2s infinite ease-in-out;animation:bounce 2s infinite ease-in-out}.baguetteBox-double-bounce2{-webkit-animation-delay:-1s;animation-delay:-1s}@-webkit-keyframes bounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounce{0%,100%{-webkit-transform:scale(0);-moz-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);-moz-transform:scale(1);transform:scale(1)}} -------------------------------------------------------------------------------- /source/js/lib/lightbox/baguetteBox.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * baguetteBox.js 3 | * @author feimosi 4 | * @version 1.11.1 5 | * @url https://github.com/feimosi/baguetteBox.js 6 | */ 7 | !function(e,t){"use strict";"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.baguetteBox=t()}(this,function(){"use strict";var r,l,u,c,d,f='',g='',p='',b={},v={captions:!0,buttons:"auto",fullScreen:!1,noScrollbars:!1,bodyClass:"baguetteBox-open",titleTag:!1,async:!1,preload:2,animation:"slideIn",afterShow:null,afterHide:null,onChange:null,overlayBackgroundColor:"rgba(0,0,0,.8)"},m={},h=[],o=0,n=!1,i={},a=!1,y=/.+\.(gif|jpe?g|png|webp)/i,w={},k=[],s=null,x=function(e){-1!==e.target.id.indexOf("baguette-img")&&j()},E=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,D()},C=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,X()},B=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,j()},T=function(e){i.count++,1
',b.captions&&s){var u=J("figcaption");u.id="baguetteBox-figcaption-"+t,u.innerHTML=s,l.appendChild(u)}e.appendChild(l);var c=J("img");c.onload=function(){var e=document.querySelector("#baguette-img-"+t+" .baguetteBox-spinner");l.removeChild(e),!b.async&&n&&n()},c.setAttribute("src",r),c.alt=a&&a.alt||"",b.titleTag&&s&&(c.title=s),l.appendChild(c),b.async&&n&&n()}}function X(){return M(o+1)}function D(){return M(o-1)}function M(e,t){return!n&&0<=e&&e=k.length?(b.animation&&O("right"),!1):(q(o=e,function(){z(o),V(o)}),R(),b.onChange&&b.onChange(o,k.length),!0)}function O(e){l.className="bounce-from-"+e,setTimeout(function(){l.className=""},400)}function R(){var e=100*-o+"%";"fadeIn"===b.animation?(l.style.opacity=0,setTimeout(function(){m.transforms?l.style.transform=l.style.webkitTransform="translate3d("+e+",0,0)":l.style.left=e,l.style.opacity=1},400)):m.transforms?l.style.transform=l.style.webkitTransform="translate3d("+e+",0,0)":l.style.left=e}function z(e){e-o>=b.preload||q(e+1,function(){z(e+1)})}function V(e){o-e>=b.preload||q(e-1,function(){V(e-1)})}function U(e,t,n,o){e.addEventListener?e.addEventListener(t,n,o):e.attachEvent("on"+t,function(e){(e=e||window.event).target=e.target||e.srcElement,n(e)})}function W(e,t,n,o){e.removeEventListener?e.removeEventListener(t,n,o):e.detachEvent("on"+t,n)}function G(e){return document.getElementById(e)}function J(e){return document.createElement(e)}return[].forEach||(Array.prototype.forEach=function(e,t){for(var n=0;n>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((c=d(d(t,n),d(e,u)))<<(f=o)|c>>>32-f,r);var c,f}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function i(n,t){var r,e,o,u;n[t>>5]|=128<>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32&255);return t}function h(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return a(i(h(t=r(n)),8*t.length));var t}function u(n,t){return function(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,16code{position:relative;border-left:10px solid #358ccb;box-shadow:-1px 0 0 0 #358ccb,0 0 0 1px #dfdfdf;background-color:#fdfdfd;background-image:linear-gradient(transparent 50%,rgba(69,142,209,.04) 50%);background-size:3em 3em;background-origin:content-box;background-attachment:local}code[class*=language]{max-height:inherit;height:inherit;padding:0 1em;display:block;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdfdfd;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-bottom:1em}:not(pre)>code[class*=language-]{position:relative;padding:.2em;border-radius:.3em;color:#c92c2c;border:1px solid rgba(0,0,0,.1);display:inline;white-space:normal}pre[class*=language-]:after,pre[class*=language-]:before{content:'';z-index:-2;display:block;position:absolute;bottom:.75em;left:.18em;width:40%;height:20%;max-height:13em;box-shadow:0 13px 8px #979797;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg)}:not(pre)>code[class*=language-]:after,pre[class*=language-]:after{right:.75em;left:auto;-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg)}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#7d8b99}.token.punctuation{color:#5f6364}.token.boolean,.token.constant,.token.deleted,.token.function-name,.token.number,.token.property,.token.symbol,.token.tag{color:#c92c2c}.token.attr-name,.token.builtin,.token.char,.token.function,.token.inserted,.token.selector,.token.string{color:#2f9c0a}.token.entity,.token.operator,.token.url,.token.variable{color:#a67f59;background:rgba(255,255,255,.5)}.token.atrule,.token.attr-value,.token.class-name,.token.keyword{color:#1990b8}.token.important,.token.regex{color:#e90}.language-css .token.string,.style .token.string{color:#a67f59;background:rgba(255,255,255,.5)}.token.important{font-weight:400}.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.namespace{opacity:.7}@media screen and (max-width:767px){pre[class*=language-]:after,pre[class*=language-]:before{bottom:14px;box-shadow:none}}.token.cr:before,.token.lf:before,.token.tab:not(:empty):before{color:#e0d7d1}pre[class*=language-].line-numbers.line-numbers{padding-left:0}pre[class*=language-].line-numbers.line-numbers code{padding-left:3.8em}pre[class*=language-].line-numbers.line-numbers .line-numbers-rows{left:0}pre[class*=language-][data-line]{padding-top:0;padding-bottom:0;padding-left:0}pre[data-line] code{position:relative;padding-left:4em}pre .line-highlight{margin-top:0} 8 | /*# sourceMappingURL=/sm/c73a084ad016251bbbbe892ab95de64b19a6eeb3c2d86ba5539be7e21f56cd1f.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-dark.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism-dark.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;text-shadow:0 -.1em .2em #000;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}:not(pre)>code[class*=language-],pre[class*=language-]{background:#4c3f33}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border:.3em solid #7a6651;border-radius:.5em;box-shadow:1px 1px .5em #000 inset}:not(pre)>code[class*=language-]{padding:.15em .2em .05em;border-radius:.3em;border:.13em solid #7a6651;box-shadow:1px 1px .3em -.1em #000 inset;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#997f66}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.number,.token.property,.token.symbol,.token.tag{color:#d1939e}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#bce051}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f4b73d}.token.atrule,.token.attr-value,.token.keyword{color:#d1939e}.token.important,.token.regex{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.deleted{color:red} 8 | /*# sourceMappingURL=/sm/97e557e95df7de597f3d7ae3a86d56e83c99bc3130fb9d0ceda00fe9d703ed07.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-funky.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism-funky.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:.4em .8em;margin:.5em 0;overflow:auto;background:url('data:image/svg+xml;charset=utf-8,%0D%0A%0D%0A%0D%0A<%2Fsvg>');background-size:1em 1em}code[class*=language-]{background:#000;color:#fff;box-shadow:-.3em 0 0 .3em #000,.3em 0 0 .3em #000}:not(pre)>code[class*=language-]{padding:.2em;border-radius:.3em;box-shadow:none;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#aaa}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.number,.token.property,.token.symbol,.token.tag{color:#0cf}.token.attr-name,.token.builtin,.token.char,.token.selector,.token.string{color:#ff0}.language-css .token.string,.token.entity,.token.inserted,.token.operator,.token.url,.token.variable{color:#9acd32}.token.atrule,.token.attr-value,.token.keyword{color:#ff1493}.token.important,.token.regex{color:orange}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.deleted{color:red}pre.diff-highlight.diff-highlight>code .token.deleted:not(.prefix),pre>code.diff-highlight.diff-highlight .token.deleted:not(.prefix){background-color:rgba(255,0,0,.3);display:inline}pre.diff-highlight.diff-highlight>code .token.inserted:not(.prefix),pre>code.diff-highlight.diff-highlight .token.inserted:not(.prefix){background-color:rgba(0,255,128,.3);display:inline} 8 | /*# sourceMappingURL=/sm/97d19382f4cc980bcf43a22534277f236150c175652422db18877bcfa4253a9a.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-line-numbers.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/plugins/line-numbers/prism-line-numbers.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right} 8 | /*# sourceMappingURL=/sm/1804facaffb0dda5677f475a30cb4fd7f2e7e69d20f3351c07dc9498191181a4.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-okaidia.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism-okaidia.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} 8 | /*# sourceMappingURL=/sm/4d06843ca8b863038763f80d48cfee31fe7ab0b4328ab710c2c57eac6af458e3.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-solarizedlight.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism-solarizedlight.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{color:#657b83;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{background:#073642}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{background:#073642}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdf6e3}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#93a1a1}.token.punctuation{color:#586e75}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#268bd2}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string,.token.url{color:#2aa198}.token.entity{color:#657b83;background:#eee8d5}.token.atrule,.token.attr-value,.token.keyword{color:#859900}.token.class-name,.token.function{color:#b58900}.token.important,.token.regex,.token.variable{color:#cb4b16}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} 8 | /*# sourceMappingURL=/sm/2ebe3d0f213efcab2d9cb741c6a641a03620362e8e35f672019c372c387107d2.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-tomorrow.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism-tomorrow.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green} 8 | /*# sourceMappingURL=/sm/1b15fe2971998a048aebb60f26f6eed76122071db9ef3b995abd003224f52a98.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism-twilight.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism-twilight.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;text-shadow:0 -.1em .2em #000;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}:not(pre)>code[class*=language-],pre[class*=language-]{background:#141414}pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:#27292a}pre[class*=language-]::selection{background:#27292a}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:hsla(0,0%,93%,.15)}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:hsla(0,0%,93%,.15)}:not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#f9ed99}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#909e6a}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}pre[data-line]{padding:1em 0 1em 3em;position:relative}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#ac885c}.token{position:relative;z-index:1}.line-highlight{background:hsla(0,0%,33%,.25);background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;left:0;line-height:inherit;margin-top:.75em;padding:inherit 0;pointer-events:none;position:absolute;right:0;white-space:pre;z-index:0}.line-highlight:before,.line-highlight[data-end]:after{background-color:#8693a6;border-radius:999px;box-shadow:0 1px #fff;color:#f4f1ef;content:attr(data-start);font:bold 65%/1.5 sans-serif;left:.6em;min-width:1em;padding:0 .5em;position:absolute;text-align:center;text-shadow:none;top:.4em;vertical-align:.3em}.line-highlight[data-end]:after{bottom:.4em;content:attr(data-end);top:auto} 8 | /*# sourceMappingURL=/sm/4ab7eb92c4592b58ef2bb686cf2b45782b104a9491464bbe30b090a7296eff69.map */ -------------------------------------------------------------------------------- /source/js/lib/prism/prism.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v4.2.1. 3 | * Original file: /npm/prismjs@1.20.0/themes/prism.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} 8 | /*# sourceMappingURL=/sm/928e23e6b9fcef82c5f1d1f05b6f7fc5a6e187c60195e59fbf16fc9d071ee057.map */ -------------------------------------------------------------------------------- /source/js/main.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";console.log(" \nThis blog is using hexo-theme-kaze based on MIT license\nSee theme at https://github.com/theme-kaze/hexo-theme-kaze\n");const e=document.body.scrollWidth||document.documentElement.scrollWidth;let t=null;function o(e){const t=e.target,n=document.getElementById("mobiletoc");n&&t&&!n.contains(t)&&(n.style.display="none",window.mask.remove(),document.removeEventListener("click",o))}window.searchControlButton=null,e<=742?(t=document.getElementsByClassName("darkwidget")[0],window.searchControlButton=document.getElementsByClassName("searchwidget")[0]):(t=document.getElementsByClassName("darknavbar")[0],window.searchControlButton=document.getElementsByClassName("searchnavbar")[0]),t.addEventListener("click",(()=>{window.setDarkmode(window.reverseDarkModeSetting())}));const n=()=>{const e=document.getElementById("mobiletoc");if(!e)return;e.style.display="block";const t=document.createElement("div");t.id="mask",document.body.append(t),setTimeout((()=>{document.addEventListener("click",o)}),0)};setTimeout((()=>{const e=document.getElementById("menubutton");e&&(e.onclick=n)}),0);const l=()=>{const e=document.getElementById("scrollbutton"),t=document.getElementById("menubutton"),o=document.getElementById("popbutton"),n=document.body.scrollWidth||document.documentElement.scrollWidth;"1"===e.style.opacity?(e.style.bottom="32px",e.style.opacity="0",o.style.transform="none"):(o.style.transform="rotate(90deg)",e.style.bottom="85px",e.style.opacity="1");const l=document.getElementById("mobiletoc");n<=862&&l&&("1"===t.style.opacity?(t.style.right="32px",t.style.opacity="0"):(t.style.right="85px",t.style.opacity="1"));const s=document.querySelector(".darkwidget"),c=document.querySelector(".searchwidget");n<=742&&("1"===s.style.opacity?(s.style.bottom="32px",s.style.opacity="0",s.style.transform="none"):(s.style.display="flex",o.style.transform="rotate(90deg)",s.style.bottom="138px",s.style.opacity="1"),"1"===c.style.opacity?(c.style.bottom="32px",c.style.opacity="0",c.style.transform="none"):(c.style.display="flex",c.style.transform="rotate(90deg)",c.style.bottom="191px",c.style.opacity="1"))};setTimeout((()=>{document.getElementById("popbutton").addEventListener("click",l)}),0);const s=()=>{let e=window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop;e>1?(window.requestAnimationFrame(s),scrollTo(0,Math.floor(.85*e))):scrollTo(0,0)};function c(e){const t=document.querySelector("#local-search");if(!t.contains(e.target)){const e=document.querySelector("#search-input"),o=document.querySelector("#search-content");e.value="",t.style.display="none",o.innerHTML="",window.mask.remove(),document.removeEventListener("click",c)}}setTimeout((()=>{const e=document.getElementById("scrollbutton");e&&(e.onclick=s)}),0),setTimeout((()=>{window.searchControlButton&&window.searchControlButton.addEventListener("click",(()=>{const e=document.createElement("div");e.id="mask",document.body.append(e);document.querySelector("#local-search").style.display="block",setTimeout((()=>{document.addEventListener("click",c)}),0)}))})),window.localSearch=function(e){fetch(e).then((e=>e.json())).then((e=>{let t=document.getElementById("search-input"),o=document.getElementById("search-content");t.addEventListener("input",(function(){let t='
    ',n=this.value.trim().toLowerCase().replace(/[<>&"]/g,(e=>({"<":"<",">":">","&":"&",'"':"""}[e])));if(o.innerHTML="",!(this.value.trim().length<=0)){if(e.forEach((function(e){let o=!0;e.title&&""!==e.title.trim()||(e.title="Untitled");let l=e.title.trim().toLowerCase();const s=e.content.trim().replace(/<[^>]+>/g,"").toLowerCase();let c=-1;const i=l.indexOf(n);let r=0;if(""!==s&&(r=s.indexOf(n),c=r),i<0&&r<0&&(o=!1),r<0&&(c=0),o){t+=`
  • '${l}`;const o=e.content;if(c>=0){const e=Math.max(0,c-12),l=Math.min(o.length,c+12);let s=o.substr(e,l);s=s.replace(new RegExp(n,"gi"),''+n+""),t+='

    '+s+"...

    "}t+="
  • "}})),t+="
",-1===t.indexOf("
  • "))return o.innerHTML='
      没有搜索到结果
    ';o.innerHTML=t}}))}))}}(); 2 | -------------------------------------------------------------------------------- /src/scripts/console.ts: -------------------------------------------------------------------------------- 1 | console.log(` 2 | This blog is using hexo-theme-kaze based on MIT license\nSee theme at https://github.com/theme-kaze/hexo-theme-kaze 3 | `) 4 | -------------------------------------------------------------------------------- /src/scripts/darkMode.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | setDarkmode: Function 3 | reverseDarkModeSetting: Function 4 | searchControlButton: Element | null 5 | } 6 | const scrollWidth = 7 | document.body.scrollWidth || document.documentElement.scrollWidth 8 | let darkControlButton = null 9 | window.searchControlButton = null 10 | if (scrollWidth <= 742) { 11 | darkControlButton = document.getElementsByClassName('darkwidget')[0] 12 | window.searchControlButton = document.getElementsByClassName('searchwidget')[0] 13 | } else { 14 | darkControlButton = document.getElementsByClassName('darknavbar')[0] 15 | window.searchControlButton = document.getElementsByClassName('searchnavbar')[0] 16 | } 17 | 18 | darkControlButton.addEventListener('click', () => { 19 | window.setDarkmode(window.reverseDarkModeSetting()) 20 | }) 21 | -------------------------------------------------------------------------------- /src/scripts/index.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | setDarkmode: Function 3 | reverseDarkModeSetting: Function 4 | mask: HTMLElement 5 | localSearch: Function 6 | } 7 | -------------------------------------------------------------------------------- /src/scripts/main.ts: -------------------------------------------------------------------------------- 1 | import './console' 2 | import './darkMode' 3 | import './menuButton' 4 | import './popButton' 5 | import './scrollUp' 6 | import './search' 7 | -------------------------------------------------------------------------------- /src/scripts/menuButton.ts: -------------------------------------------------------------------------------- 1 | function menuClick(event: Event) { 2 | const target = event.target 3 | const mobileToc = document.getElementById('mobiletoc') 4 | if (!mobileToc) { 5 | return 6 | } 7 | if (target && !mobileToc.contains(target as Node)) { 8 | mobileToc.style.display = 'none' 9 | window.mask.remove() 10 | document.removeEventListener('click', menuClick) 11 | } 12 | } 13 | const clickMenuButton = () => { 14 | const mobileToc = document.getElementById('mobiletoc') 15 | if (!mobileToc) { 16 | return 17 | } 18 | mobileToc.style.display = 'block' 19 | const mask = document.createElement('div') 20 | mask.id = 'mask' 21 | document.body.append(mask) 22 | setTimeout(() => { 23 | document.addEventListener('click', menuClick) 24 | }, 0) 25 | } 26 | setTimeout(() => { 27 | const menuButton = document.getElementById('menubutton') 28 | menuButton ? (menuButton.onclick = clickMenuButton) : void 0 29 | }, 0) 30 | -------------------------------------------------------------------------------- /src/scripts/popButton.ts: -------------------------------------------------------------------------------- 1 | const reversePopButton = () => { 2 | const scrollButton = document.getElementById('scrollbutton') as HTMLElement 3 | const menuButton = document.getElementById('menubutton') as HTMLElement 4 | const reverseButton = document.getElementById('popbutton') as HTMLElement 5 | const scrollWidth = 6 | document.body.scrollWidth || document.documentElement.scrollWidth 7 | if (scrollButton.style.opacity === '1') { 8 | scrollButton.style.bottom = '32px' 9 | scrollButton.style.opacity = '0' 10 | reverseButton.style.transform = 'none' 11 | } else { 12 | reverseButton.style.transform = 'rotate(90deg)' 13 | scrollButton.style.bottom = '85px' 14 | scrollButton.style.opacity = '1' 15 | } 16 | const mobileToc = document.getElementById('mobiletoc') 17 | if (scrollWidth <= 862 && mobileToc) { 18 | if (menuButton.style.opacity === '1') { 19 | menuButton.style.right = '32px' 20 | menuButton.style.opacity = '0' 21 | } else { 22 | menuButton.style.right = '85px' 23 | menuButton.style.opacity = '1' 24 | } 25 | } 26 | const darkButton = document.querySelector('.darkwidget') as HTMLElement 27 | const searchButton = document.querySelector('.searchwidget') as HTMLElement 28 | if (scrollWidth <= 742) { 29 | if (darkButton.style.opacity === '1') { 30 | darkButton.style.bottom = '32px' 31 | darkButton.style.opacity = '0' 32 | darkButton.style.transform = 'none' 33 | } else { 34 | darkButton.style.display = 'flex' 35 | reverseButton.style.transform = 'rotate(90deg)' 36 | darkButton.style.bottom = '138px' 37 | darkButton.style.opacity = '1' 38 | } 39 | 40 | if (searchButton.style.opacity === '1') { 41 | searchButton.style.bottom = '32px' 42 | searchButton.style.opacity = '0' 43 | searchButton.style.transform = 'none' 44 | } else { 45 | searchButton.style.display = 'flex' 46 | searchButton.style.transform = 'rotate(90deg)' 47 | searchButton.style.bottom = '191px' 48 | searchButton.style.opacity = '1' 49 | } 50 | } 51 | } 52 | setTimeout(() => { 53 | (document 54 | .getElementById('popbutton') as HTMLElement) 55 | .addEventListener('click', reversePopButton) 56 | }, 0) 57 | -------------------------------------------------------------------------------- /src/scripts/rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from '@rollup/plugin-typescript' 2 | import { terser } from 'rollup-plugin-terser' 3 | 4 | export default { 5 | input: './main.ts', 6 | output: { 7 | file: '../../source/js/main.js', 8 | format: 'iife', 9 | }, 10 | plugins: [typescript(), terser()], 11 | } 12 | -------------------------------------------------------------------------------- /src/scripts/scrollUp.ts: -------------------------------------------------------------------------------- 1 | const smoothScrollToTop = () => { 2 | let yTopValve = 3 | window.pageYOffset || 4 | document.body.scrollTop || 5 | document.documentElement.scrollTop 6 | if (yTopValve > 1) { 7 | window.requestAnimationFrame(smoothScrollToTop) 8 | scrollTo(0, Math.floor(yTopValve * 0.85)) 9 | } else { 10 | scrollTo(0, 0) 11 | } 12 | } 13 | setTimeout(() => { 14 | const scrollButton = document.getElementById('scrollbutton') 15 | scrollButton 16 | ? (scrollButton.onclick = smoothScrollToTop) 17 | : void 0 18 | }, 0) 19 | -------------------------------------------------------------------------------- /src/scripts/search.ts: -------------------------------------------------------------------------------- 1 | function htmlEscape(h: string) { 2 | return h.replace(/[<>&"]/g, (i) => { 3 | return { '<': '<', '>': '>', '&': '&', '"': '"' }[ 4 | i 5 | ] as string 6 | }) 7 | } 8 | 9 | function searchClick(event: Event) { 10 | const searchContent = document.querySelector('#local-search') as HTMLElement 11 | if (!searchContent.contains(event.target as Node)) { 12 | const searchInput = document.querySelector( 13 | '#search-input' 14 | ) as HTMLInputElement 15 | const content = document.querySelector('#search-content') as HTMLElement 16 | searchInput.value = '' 17 | searchContent.style.display = 'none' 18 | content.innerHTML = '' 19 | window.mask.remove() 20 | document.removeEventListener('click', searchClick) 21 | } 22 | } 23 | 24 | setTimeout(() => { 25 | if (window.searchControlButton) { 26 | window.searchControlButton.addEventListener('click', () => { 27 | const mask = document.createElement('div') 28 | mask.id = 'mask' 29 | document.body.append(mask) 30 | const searchMain = document.querySelector('#local-search') as HTMLElement 31 | searchMain.style.display = 'block' 32 | setTimeout(() => { 33 | document.addEventListener('click', searchClick) 34 | }, 0) 35 | }) 36 | } 37 | }) 38 | 39 | // eslint-disable-next-line no-unused-vars 40 | window.localSearch = function (path: string) { 41 | fetch(path) 42 | .then((res) => res.json()) 43 | .then((res) => { 44 | let input = document.getElementById('search-input') as HTMLInputElement 45 | let resultContent = document.getElementById( 46 | 'search-content' 47 | ) as HTMLElement 48 | 49 | input.addEventListener('input', function () { 50 | let str = '
      ' 51 | let keyword = htmlEscape(this.value.trim().toLowerCase()) 52 | resultContent.innerHTML = '' 53 | if (this.value.trim().length <= 0) { 54 | return 55 | } 56 | res.forEach(function (data: any) { 57 | let isMatch = true 58 | if (!data.title || data.title.trim() === '') { 59 | data.title = 'Untitled' 60 | } 61 | let dataTitle = data.title.trim().toLowerCase() 62 | const dataContent = data.content 63 | .trim() 64 | .replace(/<[^>]+>/g, '') 65 | .toLowerCase() 66 | let firstOccur = -1 67 | let titleOccur = -1 68 | const indexTitle = dataTitle.indexOf(keyword) 69 | titleOccur = indexTitle 70 | let indexContent = 0 71 | if (dataContent !== '') { 72 | indexContent = dataContent.indexOf(keyword) 73 | firstOccur = indexContent 74 | } 75 | if (indexTitle < 0 && indexContent < 0) { 76 | isMatch = false 77 | } 78 | if (indexContent < 0) { 79 | firstOccur = 0 80 | } 81 | if (indexTitle < 0) { 82 | titleOccur = 0 83 | } 84 | if (isMatch) { 85 | str += `
    • '${dataTitle}` 86 | const content = data.content 87 | if (firstOccur >= 0) { 88 | const start = Math.max(0, firstOccur - 12) 89 | const end = Math.min(content.length, firstOccur + 12) 90 | let matchContent = content.substr(start, end) 91 | matchContent = matchContent.replace( 92 | new RegExp(keyword, 'gi'), 93 | '' + keyword + '' 94 | ) 95 | str += '

      ' + matchContent + '...

      ' 96 | } 97 | str += '
    • ' 98 | } 99 | }) 100 | str += '
    ' 101 | if (str.indexOf('
  • ') === -1) { 102 | return (resultContent.innerHTML = 103 | '
      没有搜索到结果
    ') 104 | } 105 | resultContent.innerHTML = str 106 | }) 107 | }) 108 | } 109 | -------------------------------------------------------------------------------- /src/scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "ESNext", 5 | "lib": ["dom", "es5", "es6", "ESNext"], 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmitHelpers": true 10 | } 11 | } 12 | --------------------------------------------------------------------------------