更新主题

This commit is contained in:
DefectingCat
2020-11-11 21:33:59 +08:00
parent e06b5eb49a
commit 5fbba6c37b
134 changed files with 641 additions and 6828 deletions

File diff suppressed because it is too large Load Diff

6
package-lock.json generated
View File

@ -28,7 +28,7 @@
"hexo-renderer-marked": "^3.3.0",
"hexo-renderer-stylus": "^2.0.1",
"hexo-server": "^2.0.0",
"hexo-theme-fluid": "^1.8.4"
"hexo-theme-fluid": "^1.8.5"
},
"devDependencies": {
"@babel/core": "^7.12.3",
@ -2941,11 +2941,7 @@
"resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz?cache=0&sync_timestamp=1604593363910&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-1.2.13.tgz",
"integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=",
"deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.12.1"

View File

@ -34,7 +34,7 @@
"hexo-renderer-marked": "^3.3.0",
"hexo-renderer-stylus": "^2.0.1",
"hexo-server": "^2.0.0",
"hexo-theme-fluid": "^1.8.4"
"hexo-theme-fluid": "^1.8.5"
},
"devDependencies": {
"@babel/core": "^7.12.3",

View File

@ -4,6 +4,8 @@ date: 2020-02-29 13:07:34
layout: about
---
![:xfy](https://count.getloli.com/get/@:xfy?theme=rule34)
## 经历风雨
才会成长。
@ -20,5 +22,4 @@ Wordpress到typecho换来换去的主题最后还是选择了纯静态。
## 全部艺能
!@#$%^&*()
!@#$%^&*()

View File

@ -173,5 +173,5 @@ background: linear-gradient(to bottom,transparent 60%,rgba(189,202,219,.3) 0) no
position: relative;
padding-top: 10px;
background: no-repeat right bottom url(https://cdn.defectink.com/static/images/iloli.gif);
background-size: 20%;
background-size: 15%;
}

View File

@ -6,6 +6,6 @@ $(document).ready(function () {
});
// 失焦时添加回来
$("#comments").on("blur", ".v[data-class=v] .vwrap .vedit", function () {
$(this).animate({"background-size":"20%"});
$(this).animate({"background-size":"15%"});
});
});

View File

@ -1,7 +1,7 @@
---
title: pgp
date: 2020-02-23 17:03:44
comments: ture
comment: true
---
<div class="markdown-body">

View File

@ -1,13 +0,0 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@ -1,224 +0,0 @@
{
"extends": [
"eslint:recommended"
],
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
// Override recomennded
"no-console": [
2,
{
"allow": [
"warn"
]
}
],
"no-empty": [
2,
{
"allowEmptyCatch": true
}
],
"no-unused-vars": [
2,
{
"args": "none"
}
],
// Possible Errors
"no-extra-parens": [
2,
"all",
{
"conditionalAssign": false,
"returnAssign": false,
"nestedBinaryExpressions": false,
"enforceForArrowConditionals": false
}
],
// Best Practices
"array-callback-return": 2,
"block-scoped-var": 2,
"curly": [
2,
"multi-line"
],
"dot-location": [
2,
"property"
],
"dot-notation": 2,
"eqeqeq": [
2,
"smart"
],
"no-else-return": 2,
"no-eval": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-label": 2,
"no-implicit-globals": 2,
"no-implied-eval": 2,
"no-lone-blocks": 2,
"no-loop-func": 2,
"no-multi-spaces": [
2,
{
"exceptions": {
"ImportDeclaration": true,
"VariableDeclarator": true,
"FunctionDeclarator": true,
"AssignmentExpression": true,
"CallExpression": true
}
}
],
"no-multi-str": 2,
"no-new": 2,
"no-new-func": 2,
"no-new-wrappers": 2,
"no-proto": 2,
"no-return-assign": 2,
"no-self-compare": 2,
"no-sequences": 2,
"no-throw-literal": 2,
"no-unused-expressions": [
2,
{
"allowShortCircuit": true,
"allowTernary": true
}
],
"no-useless-call": 2,
"no-useless-concat": 2,
"no-useless-return": 2,
"no-void": 2,
"no-with": 2,
"prefer-promise-reject-errors": 2,
"radix": 2,
"wrap-iife": [
2,
"inside"
],
"yoda": 2,
// Variables
"no-label-var": 2,
"no-shadow-restricted-names": 2,
"no-undef-init": 2,
// Node.js and CommonJS
"handle-callback-err": 2,
"no-path-concat": 2,
// Stylistic Issues
"array-bracket-spacing": 2,
"block-spacing": 2,
"brace-style": [
2,
"1tbs",
{
"allowSingleLine": true
}
],
"comma-dangle": 2,
"comma-spacing": 2,
"comma-style": 2,
"computed-property-spacing": 2,
"eol-last": 2,
"func-call-spacing": 2,
"indent": [
2,
2,
{
"SwitchCase": 1,
"VariableDeclarator": {
"var": 2,
"let": 2,
"const": 3
}
}
],
"key-spacing": [
2,
{
"align": "colon",
"beforeColon": false
}
],
"keyword-spacing": 2,
"linebreak-style": ["off", "window"],
"lines-around-comment": 2,
"new-cap": [
2,
{
"capIsNew": false
}
],
"new-parens": 2,
"no-array-constructor": 2,
"no-mixed-operators": 2,
"no-multiple-empty-lines": 2,
"no-nested-ternary": 2,
"no-new-object": 2,
"no-trailing-spaces": 2,
"no-unneeded-ternary": 2,
"no-whitespace-before-property": 2,
"object-curly-spacing": [
2,
"always"
],
"one-var": [
2,
{
"uninitialized": "always",
"initialized": "never"
}
],
"operator-linebreak": [
2,
"before"
],
"quotes": [
2,
"single"
],
"semi": 2,
"semi-spacing": 2,
"space-before-blocks": 2,
"space-before-function-paren": [
2,
"never"
],
"space-in-parens": 2,
"space-infix-ops": 2,
"space-unary-ops": 2,
"template-tag-spacing": 2,
"unicode-bom": 2,
// ECMAScript 6
"arrow-spacing": 2,
"generator-star-spacing": [
2,
"after"
],
"no-confusing-arrow": [
2,
{
"allowParens": true
}
],
"no-duplicate-imports": 2,
"no-useless-computed-key": 2,
"no-useless-constructor": 2,
"no-useless-rename": 2,
"rest-spread-spacing": 2,
"template-curly-spacing": 2,
"yield-star-spacing": 2
},
"env": {
"browser": true,
"jquery": true,
"mocha": true,
"node": true,
"es6": true
}
}

View File

@ -1 +0,0 @@
source/lib/* linguist-vendored

View File

@ -1,27 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ':bug: bug'
assignees: ''
---
#### Make sure
- [ ] Upgrade the latest [release](https://github.com/fluid-dev/hexo-theme-fluid/releases).
- [ ] Browser does not belong to IE and other old browsers
- [ ] It can be replicated through `hexo clean && hexo s` and cleared browser cache in the localhost.
- [ ] Not affected by other Hexo plugins
#### Describe the bug
<!-- A clear and concise description of what the bug is. -->
#### To Reproduce
Steps to reproduce the behavior:
1. Go to '...', click on '....'
2. Scroll down to '....'
3. See error
<!-- It is better to provide the page link that can be reproduced -->
#### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->

View File

@ -1,31 +0,0 @@
---
name: Bug 报告
about: 创建一份 Bug 报告帮助我们优化产品
title: ''
labels: ':bug: bug'
assignees: ''
---
<!-- 必读 -->
<!-- 1. 功能如果不正常工作,请先检查自己的环境和 Hexo 插件,特别是从其他主题更换过来的用户(最简单的方式:新建目录重新 hexo init -->
<!-- 2. 只考虑本地出现的问题,如果本地运行正常,部署后有问题,这种不属于 BUG请清除缓存或者等 CDN 刷新 -->
<!-- 3. 不确定是不是 BUG 的,请后退使用问题求助 -->
#### 请确认
- [ ] 是当前最新的 [Release 版本](https://github.com/fluid-dev/hexo-theme-fluid/releases)
- [ ] 浏览器不属于 IE 等非主流浏览器
- [ ] 本地 `hexo clean && hexo s`,并且清除浏览器缓存,仍可复现
- [ ] 已经排除是其他 Hexo 插件影响
#### Bug 描述
<!-- 例如,当 xxx 时xxx 功能不工作,期望是 xxx 能工作,浏览器: Chrome -->
#### 复现步骤
该 Bug 复现步骤如下:
1. 在 xxx 页面点击 xxx 按钮
2. 然后向下滚动
3. 会出现 xxx
<!-- 最好提供部署后能复现的页面地址 -->
#### 截图

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ':sparkles: enhancement'
assignees: ''
---
#### Make sure
- [ ] Difficult to implement through [custom](https://hexo.fluid-dev.com/docs/en/guide/#custom-js-css-html).
- [ ] Difficult to implement through third-party plugins.
#### Is your feature request related to a problem? Please describe
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]. -->
#### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
#### Describe alternatives you've considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->

View File

@ -1,20 +0,0 @@
---
name: 功能需求或优化
about: 创建一份合理可行的建议帮助我们提升产品
title: ''
labels: ':sparkles: enhancement'
assignees: ''
---
#### 如是功能需求,请确定符合以下情况
- [ ] 难以通过[自定义](https://hexo.fluid-dev.com/docs/guide/#%E8%87%AA%E5%AE%9A%E4%B9%89-js-css-html)实现的功能
- [ ] 难以通过第三方插件实现
#### 请描述该需求尝试解决的问题
<!-- 例如,当 xxx 时,我总是被当前 xxx 的设计所困扰。 -->
#### 请描述您认为可行的解决方案
<!-- 例如,添加 xxx 功能能够解决问题。 -->
#### 考虑过的替代方案
<!-- 例如,如果用 xxx也能解决该问题。 -->

View File

@ -1,11 +0,0 @@
---
name: Question
about: Ask a question about use, need help
---
#### Make sure
- [ ] Upgrade the latest [release](https://github.com/fluid-dev/hexo-theme-fluid/releases)
- [ ] No solution found in [documentations](https://hexo.fluid-dev.com/docs/en/)
#### Describe the question
<!-- A clear and concise description of what the question is. -->

View File

@ -1,14 +0,0 @@
---
name: 问题求助
about: 提出一个使用过程中遇到的问题,需要得到帮助
---
#### 请确认
- [ ] 是当前最新的 [Release 版本](https://github.com/fluid-dev/hexo-theme-fluid/releases)
- [ ] 在 [用户指南](https://hexo.fluid-dev.com/docs/) 中没有找到解决办法
#### 问题描述
<!--
例如,在使用 xxx 时出现了 xxx 报错。
如果是页面问题,需要提供浏览器版本(如果本地样式没问题,部署后有问题,请清除浏览器缓存)。
-->

View File

@ -1,18 +0,0 @@
name: Limit PRs
on:
pull_request:
branches:
- master
jobs:
limit_master_pr:
runs-on: ubuntu-latest
name: Limits PR to master
steps:
- name: Limit action step
id: limit_action
uses: LukBukkit/action-pr-limits@v1
with:
whitelist: |
develop

View File

@ -1,33 +0,0 @@
name: Lint
on:
push:
branches:
- develop
pull_request:
branches:
- develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Branch
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Setup Node
uses: actions/setup-node@v1
- name: Install Node Modules
run: |
rm -f .yarnclean
yarn --frozen-lockfile --ignore-engines --ignore-optional --non-interactive --silent --ignore-scripts --production=false
env:
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
HUSKY_SKIP_INSTALL: true
- name: Run Lint
run: yarn run lint

View File

@ -1,7 +0,0 @@
.idea/
.DS_Store
*.log
*.iml
yarn.lock
package-lock.json
node_modules/

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 Fluid-dev organization
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,146 +0,0 @@
<p align="center">
<img alt="Fluid Logo" src="https://avatars2.githubusercontent.com/t/3419353?s=280&v=4" width="128">
</p>
<p align="center">一款 Material Design 风格的主题</p>
<p align="center">An elegant Material-Design theme for Hexo</p>
![ScreenShot](https://cdn.jsdelivr.net/gh/fluid-dev/static@master/hexo-theme-fluid/screenshots/index.png)
<p align="center">
<a title="Hexo Version" target="_blank" href="https://hexo.io/zh-cn/"><img alt="Hexo Version" src="https://img.shields.io/badge/Hexo-%3E%3D%203.0-orange?style=flat"></a>
<a title="Node Version" target="_blank" href="https://nodejs.org/zh-cn/"><img alt="Node Version" src="https://img.shields.io/badge/Node-%3E%3D%208.1.0-yellowgreen?style=flat"></a>
<a title="License" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/blob/master/LICENSE"><img alt="License" src="https://img.shields.io/github/license/fluid-dev/hexo-theme-fluid.svg?style=flat"></a>
<br>
<a title="GitHub Release" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/releases"><img alt="GitHub Release" src="https://img.shields.io/github/v/release/fluid-dev/hexo-theme-fluid?style=flat"></a>
<a title="GitHub Commits" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/commits/master"><img alt="GitHub Commits" src="https://img.shields.io/github/commit-activity/m/fluid-dev/hexo-theme-fluid.svg?style=flat&color=brightgreen"></a>
<a title="Last Commit" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/commits/master"><img alt="Last Commit" src="https://img.shields.io/github/last-commit/fluid-dev/hexo-theme-fluid/master.svg?style=flat&color=FF9900"></a>
<br><br>
<a title="GitHub Watchers" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/watchers"><img alt="GitHub Watchers" src="https://img.shields.io/github/watchers/fluid-dev/hexo-theme-fluid.svg?label=Watchers&style=social"></a>
<a title="GitHub Stars" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/stargazers"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/fluid-dev/hexo-theme-fluid.svg?label=Stars&style=social"></a>
<a title="GitHub Forks" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/network/members"><img alt="GitHub Forks" src="https://img.shields.io/github/forks/fluid-dev/hexo-theme-fluid.svg?label=Forks&style=social"></a>
</p>
<p align="center">🇨🇳 中文简体 | <a title="English" href="README_en.md">🇬🇧 English</a></p>
<p align="center">
<span>文档:</span>
<a href="https://hexo.fluid-dev.com/docs/guide/">主题配置</a>&nbsp&nbsp&nbsp&nbsp
<a href="https://hexo.io/zh-cn/docs/front-matter">文章配置</a>
</p>
<p align="center">
<span>预览:</span>
<a href="https://hexo.fluid-dev.com/">demo</a>&nbsp&nbsp&nbsp&nbsp
<a href="https://zkqiang.cn">zkqiang's blog</a>
</p>
## 快速开始
#### 1. 搭建 Hexo 博客
如果你还没有 Hexo 博客,请按照 [Hexo 官方文档](https://hexo.io/zh-cn/docs/) 进行安装、建站。
#### 2. 获取主题最新版本
**方式一:**
Hexo 5.0.0 版本以上,推荐通过 npm 直接安装,进入博客目录执行命令:
```sh
npm install --save hexo-theme-fluid
```
然后在博客目录下创建 `_config.fluid.yml`,将主题的 [_config.yml](https://github.com/fluid-dev/hexo-theme-fluid/blob/release/_config.yml) 内容复制过去。
**方式二:**
下载 [最新 release 版本](https://github.com/fluid-dev/hexo-theme-fluid/releases) 解压到 themes 目录,并将解压出的文件夹重命名为 `fluid`
#### 3. 指定主题
如下修改 Hexo 博客目录中的 `_config.yml`
```yaml
theme: fluid # 指定主题
language: zh-CN # 指定语言,会影响主题显示的语言,按需修改
```
#### 4. 创建「关于页」
首次使用主题的「关于页」需要手动创建:
```bash
hexo new page about
```
创建成功后,编辑博客目录下 `/source/about/index.md`,添加 `layout` 属性。
修改后的文件示例如下:
```yaml
---
title: about
date: 2020-02-23 19:20:33
layout: about
---
这里写关于页的正文,支持 Markdown, HTML
```
## 更新主题
更新主题的方式[参照这里](https://hexo.fluid-dev.com/docs/start/#更新主题)。
## 功能特性
- [x] 图片懒加载
- [x] 自定义代码高亮方案
- [x] 内置多语言
- [x] 支持多款评论插件
- [x] 支持使用[数据文件](https://hexo.io/zh-cn/docs/data-files)存放配置
- [x] 自定义静态资源 CDN
- [x] 无比详实的[用户文档](https://hexo.fluid-dev.com/docs/)
- [x] 内置文章搜索
- [x] 页脚备案信息
- [x] 网页访问统计
- [x] 支持脚注语法
- [x] 支持 LaTeX 数学公式
- [x] 支持 mermaid 流程图
- [x] 暗色模式
## 贡献者
[![contributors](https://opencollective.com/hexo-theme-fluid/contributors.svg?width=890&button=false)](https://github.com/fluid-dev/hexo-theme-fluid/graphs/contributors)
英文文档翻译:[@EatRice](https://eatrice.top/) [@橙子杀手](https://ruru.eatrice.top)
其他贡献:[@zhugaoqi](https://github.com/zhugaoqi) [@julydate](https://github.com/julydate)
如你也想贡献代码,可参照[贡献指南](https://hexo.fluid-dev.com/docs/contribute/)
## 社区
微信群:扫描二维码添加好友进交流群
<details>
<summary>二维码</summary>
<p><b>好友申请备注fluid</b></p>
<p><b>提问之前请先仔细查阅用户文档</b></p>
<img width="200" src="https://cdn.jsdelivr.net/gh/fluid-dev/static@master/hexo-theme-fluid/wechat.png" alt="wechat">
</details>
## 支持
你可以通过[爱发电](https://afdian.net/@zkqiang)支持我们的开源创作,资金将用于服务器开销以及今后的公共接口服务
<a href="https://afdian.net/@zkqiang">
<img width="300" src="https://static.zkqiang.cn/images/20200715113201.png-slim" alt="support me">
</a>
其他商业赞助可发送邮件至 zkqiang#126.com (#替换为@)
## Star 趋势
[![Stargazers over time](https://starchart.cc/fluid-dev/hexo-theme-fluid.svg)](https://starchart.cc/fluid-dev/hexo-theme-fluid)

View File

@ -1,119 +0,0 @@
<p align="center">
<img alt="Fluid Logo" src="https://avatars2.githubusercontent.com/t/3419353?s=280&v=4" width="128">
</p>
<p align="center">An elegant Material-Design theme for Hexo</p>
![ScreenShot](https://cdn.jsdelivr.net/gh/fluid-dev/static@master/hexo-theme-fluid/screenshots/index.png)
<p align="center">
<a title="Hexo Version" target="_blank" href="https://hexo.io"><img alt="Hexo Version" src="https://img.shields.io/badge/Hexo-%3E%3D%203.0-orange?style=flat"></a>
<a title="Node Version" target="_blank" href="https://nodejs.org"><img alt="Node Version" src="https://img.shields.io/badge/Node-%3E%3D%208.1.0-yellowgreen?style=flat"></a>
<a title="License" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/blob/master/LICENSE"><img alt="License" src="https://img.shields.io/github/license/fluid-dev/hexo-theme-fluid.svg?style=flat"></a>
<br>
<a title="GitHub Release" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/releases"><img alt="GitHub Release" src="https://img.shields.io/github/v/release/fluid-dev/hexo-theme-fluid?style=flat"></a>
<a title="GitHub Commits" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/commits/master"><img alt="GitHub Commits" src="https://img.shields.io/github/commit-activity/m/fluid-dev/hexo-theme-fluid.svg?style=flat&color=brightgreen"></a>
<a title="Last Commit" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/commits/master"><img alt="Last Commit" src="https://img.shields.io/github/last-commit/fluid-dev/hexo-theme-fluid/master.svg?style=flat&color=FF9900"></a>
<br><br>
<a title="GitHub Watchers" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/watchers"><img alt="GitHub Watchers" src="https://img.shields.io/github/watchers/fluid-dev/hexo-theme-fluid.svg?label=Watchers&style=social"></a>
<a title="GitHub Stars" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/stargazers"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/fluid-dev/hexo-theme-fluid.svg?label=Stars&style=social"></a>
<a title="GitHub Forks" target="_blank" href="https://github.com/fluid-dev/hexo-theme-fluid/network/members"><img alt="GitHub Forks" src="https://img.shields.io/github/forks/fluid-dev/hexo-theme-fluid.svg?label=Forks&style=social"></a>
</p>
<p align="center"><a title="Chinese" href="README.md">🇨🇳 中文简体</a> | 🇬🇧 English</p>
<p align="center">
<span>Docs</span>
<a href="https://hexo.fluid-dev.com/docs/en/guide/">Theme-Guide</a>&nbsp&nbsp&nbsp&nbsp
<a href="https://hexo.io/docs/front-matter">Post-Guide</a>
</p>
<p align="center">
<span>Preview: </span>
<a href="https://hexo.fluid-dev.com/">demo</a>&nbsp&nbsp&nbsp&nbsp
<a href="https://zkqiang.cn">zkqiang's blog</a>
</p>
## Quick Start
#### 1. Install Hexo
If you don't have a hexo blog, please follow [Hexo Docs](https://hexo.io/docs/) to install and initialize your blog。
#### 2. Download Fluid
**Way A:**
If your Hexo version >= 5.0.0, you can be installed via Npm:
```sh
npm install --save hexo-theme-fluid
```
Then create `_config.fluid.yml` in the blog directory and copy the content of [_config.yml](https://github.com/fluid-dev/hexo-theme-fluid/blob/release/_config.yml)
**Way B:**
Download the [latest release](https://github.com/fluid-dev/hexo-theme-fluid/releases), then extract it to `themes` directory and renamed to `fluid`.
#### 3. Set theme
Edit `_config.yml` in the blog root directory as follows:
```yaml
theme: fluid
```
#### 4. Create about page
The about page needs to be created manually:
```bash
hexo new page about
```
Then edit `/source/about/index.md` and add `layout` attribute.
The modified example is as follows:
```yaml
---
title: about
date: 2020-02-23 19:20:33
layout: about
---
About content
```
## How to Upgrade
[Please follow here](https://hexo.fluid-dev.com/docs/en/start/#theme-upgrade)
## Features
- [x] Image lazyload
- [x] Custom code highlighting scheme
- [x] Internationalization
- [x] Support for multiple comment plugins
- [x] Support for storing configuration in [Data Files](https://hexo.io/docs/data-files.html)
- [x] Custom static resource CDN
- [x] Detailed [documents](https://hexo.fluid-dev.com/docs/en/)
- [x] Built-in search plugin
- [x] Website analysis
- [x] Support for footnote
- [x] Support for LaTeX
- [x] Support for mermaid
- [x] Dark mode
## Contributors
[![contributors](https://opencollective.com/hexo-theme-fluid/contributors.svg?width=890&button=false)](https://github.com/fluid-dev/hexo-theme-fluid/graphs/contributors)
English docs translator[@EatRice](https://eatrice.top/) [@橙子杀手](https://ruru.eatrice.top)
Contributors outside PR[@zhugaoqi](https://github.com/zhugaoqi) [@julydate](https://github.com/julydate)
## Star Trending
[![Stargazers over time](https://starchart.cc/fluid-dev/hexo-theme-fluid.svg)](https://starchart.cc/fluid-dev/hexo-theme-fluid)

View File

@ -1,488 +0,0 @@
#---------------------------
# Hexo Fluid
# Author: Fluid-dev organization
# Github: https://github.com/fluid-dev/hexo-theme-fluid
#
# Docshttps://hexo.fluid-dev.com/docs/guide/
#---------------------------
#---------------------------
# 全局
# Site
#---------------------------
favicon: /img/favicon.png # 网站标签页的 icon
apple_touch_icon: /img/favicon.png # 用于苹果设备的 icon
title_join_string: ' - ' # 浏览器标签页中的标题分隔符,效果: 文章名 - 站点名
force_https: false # 强制所有链接升级为 HTTPS适用于图片等资源出现 HTTP 混入报错)
code: # 代码块相关的配置
copy_btn: true # 是否开启复制代码的按钮
highlight: # 代码高亮
enable: true
lib: 'highlightjs' # 实现高亮的库可选highlightjs | prismjs对应下面的配置项
highlightjs:
style: 'Github Gist' # 高亮样式见https://highlightjs.org/static/demo/ 在页面挑选 style 填入
bg_color: false # 是否根据 style 改变代码背景色,**如果 style 是深色背景别忘了开启此项**
prismjs:
style: 'default' # 高亮样式见https://prismjs.com/ 在页面右侧的圆形按钮挑选 style 填入,也可以直接填入 css 链接
preprocess: true # 设为 true 高亮将本地静态生成(并只支持部分 prismjs 插件),设为 false 高亮将在浏览器通过 js 生成
fun_features: # 一些好玩的功能
typing: # 为 subtitle 添加打字机效果
enable: true
typeSpeed: 70 # 打印速度,数字越大越慢
cursorChar: "_" # 游标字符
loop: false # 是否循环播放效果
anchorjs: # 为文章内容中的标题添加锚图标
enable: true
element: h1,h2,h3,h4,h5,h6
placement: right # icon放置的位置 left | right
visible: hover # 默认悬浮显示可选hover鼠标在元素上悬浮时显示 | always一直显示 | touch移动端触摸显示
icon: "" # 可选:§ | # | ❡ 等,留空则为默认效果
dark_mode: # 主题暗色模式,开启后菜单中会出现切换按钮,用户浏览器会存储切换选项,并且会遵循 prefers-color-scheme 自动切换
enable: true
default: auto # 默认的模式auto | light | dark选择 auto 时优先遵循 prefers-color-scheme其次按用户本地时间 18 点到次日 6 点之间进入暗色模式,**注意:当用户手动切换后则不再按照默认模式**
color: # 主题颜色配置,不一定能每一处都生效,可能会被局部样式覆盖,这种情况建议用自定义 css 解决。配色可以在这获得启发: https://www.webdesignrankings.com/resources/lolcolors/
body_bg_color: "#eee" # body 背景色
body_bg_color_dark: "#181c27" # 暗色模式下的 body 背景色,下同
navbar_bg_color: "#2f4154" # 顶部菜单背景色
navbar_bg_color_dark: "#1f3144"
navbar_text_color: "#fff" # 顶部菜单字体色
navbar_text_color_dark: "#d0d0d0"
text_color: "#3c4858" # 全局字体色
text_color_dark: "#c4c6c9"
sec_text_color: "#718096" # 全局次级字体色(摘要、简介等位置)
sec_text_color_dark: "#a7a9ad"
post_text_color: "#2c3e50" # 文章正文字体色
post_text_color_dark: "#c4c6c9"
post_heading_color: "#1a202c" # 文章标题标签字体色h1 h2 h3...
post_heading_color_dark: "#c4c6c9"
post_link_color: "#0366d6" # 文章超链接字体色
post_link_color_dark: "#1589e9"
link_hover_color: "#30a9de" # 超链接悬浮时字体色
link_hover_color_dark: "#30a9de"
link_hover_bg_color: "#f8f9fa" # 超链接悬浮背景色
link_hover_bg_color_dark: "#364151"
board_color: "#fff" # 主面板背景色
board_color_dark: "#252d38"
font: # 主题字体配置
font_size: 16px # 全局字号
font_family: # 全局字体
code_font_size: 85% # 代码的字号
custom_js: # 指定自定义 js 文件路径,路径是相对 source 目录,如 /js/custom.js 对应存放目录 source/js/custom.js支持列表
custom_css: # 指定自定义 css 文件路径,路径是相对 source 目录,如 /css/custom.css 同上,支持列表
custom_html: '' # 自定义底部 HTML 内容(位于 footer 上方),也可用于外部引入 js css 这些操作,注意不要和 post.custom 配置冲突
web_analytics: # 网页访问统计
enable: false
baidu: # 百度统计的 Key参见 https://tongji.baidu.com/sc-web/10000033910/home/site/getjs?siteId=13751376 代码获取中 hm.js? 后边的字符串
google: # Google 统计的 Tracking ID参见 https://analytics.google.com/analytics/web/
gtag: # Google gtag.js 的媒体资源 ID参见 https://analytics.google.com/analytics/web/ 中的 管理 -> 媒体资源设置 -> 跟踪 ID
tencent: # 腾讯统计的 H5 App id参见 https://mta.qq.com/h5/manage/ctr_app_manage (开启高级功能才有cid)
sid:
cid:
woyaola: # 51.la 站点统计 ID参见 https://www.51.la/user/site/index
cnzz: # 友盟/cnzz 站点统计 web_id参见 https://web.umeng.com/main.php?c=site&a=show
leancloud: # LeanCloud 计数统计,可用于 PV UV 展示,如果 web_analytics.enable 没有开启PV UV 展示只会查询,不会增加
app_id:
app_key:
server_url: # REST API 服务器地址,国际版不填
lazyload: # 对页面中的图片进行懒加载处理,可见范围外的图片不会加载
enable: true
onlypost: false # 仅在文章页使用懒加载,开启后如果自定义页面需要使用,可以在 Front-matter 里指定 `lazyload: true`
version: # 主题版本相关
check: false # 每次生成页面后,检测主题是否为最新版本
#---------------------------
# 页头
# Header
#---------------------------
navbar:
blog_title: Fluid # 导航栏左侧的标题,为空则按 hexo config.title 显示
ground_glass: # 导航栏毛玻璃特效,实验性功能,可能会造成页面滚动掉帧和抖动,部分浏览器不支持会自动不生效
enable: false
px: 3 # 模糊像素,只能为数字,数字越大模糊度越高
alpha: 0.7 # 透明度,只能为数字,范围 0~1数字越大透明度越低注意透明过度可能看不清菜单字体
menu: # 可自行增减key 用来关联 languages/*.yml如不存在关联则显示 key 本身的值icon 是 css class可以省略增加 name 可以强制显示指定名称
- { key: 'home', link: '/', icon: 'iconfont icon-home-fill' }
- { key: 'archive', link: '/archives/', icon: 'iconfont icon-archive-fill' }
- { key: 'category', link: '/categories/', icon: 'iconfont icon-category-fill' }
- { key: 'tag', link: '/tags/', icon: 'iconfont icon-tags-fill' }
- { key: 'about', link: '/about/', icon: 'iconfont icon-user-fill' }
#- { key: 'links', link: '/links/', icon: 'iconfont icon-link-fill' } # 友链页,把前面#去掉即可展示
search: # 搜索栏,基于 hexo-generator-search 插件,若已安装其他搜索插件请关闭此功能,以避免生成多余的索引文件。
enable: true
path: /local-search.xml # 文件引用地址,默认是下方生成位置,也可以将生成后的 local-search.xml 上传到其它位置引用https://www.example.com/local-search.xml
generate_path: /local-search.xml # 文件生成位置,必须为相对位置
field: post
content: true
scroll_down_arrow: # 向下滚动的箭头
enable: true
banner_height_limit: 90 # 头图高度不小于指定比例,才显示箭头
scroll_after_turning_page: true # 翻页后自动滚动
banner_parallax: true # 头图滚动视差
#---------------------------
# 页脚
# Footer
#---------------------------
footer:
content: '
<a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
<i class="iconfont icon-love"></i>
<a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a>
' # 页脚第一行文字的 HTML建议保留 Fluid 的链接,用于向更多人推广本主题
statistics: # 展示网站的 PV、UV 统计数
enable: false
source: "busuanzi" # 统计数据来源可选busuanzi | leancloud使用 leancloud 需要在 web_analytics 中设置 api 参数,使用 busuanzi 注意可能间歇抽风
pv_format: "总访问量 {} 次" # 显示的文本,{}是数字的占位符(必须包含),下同
uv_format: "总访客数 {} 人"
beian: # The footer of China's website policy, other areas keep disable
enable: false
icp_text: 京ICP证123456号 # ICP证号
police_text: 京公网安备12345678号 # 公安备案号不填则只显示ICP
police_code: 12345678 # 公安备案的编号用于URL跳转查询
police_icon: /img/police_beian.png # 公安备案的图片. 为空时不显示备案图片
scroll_top_arrow: # 向顶部滚动的箭头
enable: true
#---------------------------
# 首页
# Index Page
#---------------------------
index:
banner_img: /img/default.png # 首页 Banner 头图,以下相同
banner_img_height: 100 # 头图高度屏幕百分比available: 0 - 100
banner_mask_alpha: 0.3 # 头图黑色蒙版的透明度available: 0 - 1.0 0 是完全透明无蒙版1 是完全不透明
post_default_img: '' # 默认的文章封面图,当没有指定 index_img 时会使用该图片,若都为空则不显示任何图片
slogan: # 首页副标题的独立设置
enable: true # 为 false 则不显示任何内容
text: 'An elegant Material-Design theme for Hexo' # 为空则按 hexo config.subtitle 显示
auto_excerpt:
enable: true
post_url_target: _self # available: _blank | _self
post_meta: # 是否显示文章信息(时间、分类、标签)
date: true
category: true
tag: true
post_sticky: # 文章通过 sticky 排序后,在首页文章标题前显示图标
enable: true
icon: 'iconfont icon-top'
# 通过 hexo new page 命令创建的页面
# Custom Page
page:
banner_img: /img/default.png
banner_img_height: 60 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
#---------------------------
# 文章页
# Post Page
#---------------------------
post: # 部分配置同时控制自定义页面,注意备注
banner_img: /img/default.png
banner_img_height: 70 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
meta: # 文章标题下方的信息
author: # 作者,优先根据 front-matter 里 author 字段,其次是 hexo 配置中 author 值
enable: true
date: # 文章日期,优先根据 front-matter 里 date 字段,其次是 md 文件日期
enable: true
format: "LL a" # 格式参照 ISO-8601 日期格式化,可参照 http://momentjs.cn/docs/#/parsing/string-format/
wordcount: # 字数统计
enable: true
format: "{} 字" # 显示的文本,{}是数字的占位符(必须包含),下同
min2read: # 阅读时间
enable: true
format: "{} 分钟"
words: 100 # 每分钟阅读多少字,如果是技术文章,建议降低
views: # 阅读次数
enable: false
source: "busuanzi" # 统计数据来源可选busuanzi | leancloud使用 leancloud 需要在 web_analytics 中设置 api 参数,使用 busuanzi 注意可能间歇抽风
format: "{} 次"
updated: # 在文章开头显示文章更新时间,该时间默认是 md 文件更新时间,可通过 front-matter 中 `updated` 手动指定(和 date 一样格式)
enable: false
content: 本文最后更新于: # 描述文字
relative: false # 是否使用相对时间表示,比如:"3 天前"
toc: # 文章右侧目录
enable: true
headingSelector: h1,h2,h3,h4,h5,h6
collapseDepth: 0 # 层级的折叠深度0 是全部折叠6 是全部不折叠
copyright: # 版权声明
enable: true
content: '本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener">CC BY-SA 4.0 协议</a> ,转载请注明出处!'
prev_next: # 文章底部上一篇下一篇功能
enable: true
custom: # 文章底部自定义内容
enable: false
content: '<img src="https://octodex.github.com/images/jetpacktocat.png" class="rounded mx-auto d-block mt-5" style="width:150px; height:150px;">' # 自定义区域,支持 HTML可自行插入赞赏码、公众号二维码等内容
image_zoom: # 文章图片可点击放大
enable: true # 开启后文章默认可用,自定义页面如需使用,需在 Front-matter 中指定 `image_zoom: true`,并且图片使用该格式插入:<img src="..." zoom />
footnote: # 脚注语法,会在文章底部生成脚注,如果 Markdown 渲染器本身支持,则建议关闭,否则可能会冲突
enable: true
header: '' # 脚注的节标题,也可以在 front-matter 中通过 `footnote: <h2>Reference</h2>` 这种形式修改单页的节标题
math: # 数学公式,开启之前需要更换 Markdown 渲染器否则复杂公式会有兼容问题具体请见https://hexo.fluid-dev.com/docs/guide/##latex-数学公式
enable: false # 开启后文章默认可用,自定义页面如需使用,需在 Front-matter 中指定 `math: true`
specific: false # 开启后,只有在文章 Front-matter 里指定 `math: true` 才会在文章页启动公式转换,以便在页面不包含公式时提高加载速度
engine: mathjax # 公式引擎 available: mathjax | katex
mermaid: # 流程图,基于 mermaid-js文档http://mermaid-js.github.io/mermaid/
enable: false # 开启后文章默认可用,自定义页面如需使用,需在 Front-matter 中指定 `mermaid: true`
specific: false # 开启后,只有在文章 Front-matter 里指定 `mermaid: true` 才会在文章页启动公式转换,以便在页面不包含公式时提高加载速度
options: { theme: 'default' } # 接口选项具体可见http://mermaid-js.github.io/mermaid/#/mermaidAPI
comments: # 评论
enable: false # 开启评论
type: disqus # 指定使用的评论模块 available: disqus | valine | gitalk | utterances | changyan | livere | remark42
#---------------------------
# 评论
# Comments
#---------------------------
# 开启评论需要先在上方 post.comments.enable: true
# utterances
# You can install utterances with https://utteranc.es/ and generate your configuration
utterances:
repo:
issue_term: pathname
label: utterances
theme: github-light
theme_dark: github-dark
crossorigin: anonymous
# Disqus
disqus:
shortname: # your shortname
# The following are Disqusjs configurations, please ignore if DisqusJS is not required
# 以下为 Disqusjs 支持, 国内用户如果想使用 Disqus 建议配合使用
# https://github.com/SukkaW/DisqusJS
disqusjs: false # 设置为 true 开启 DisqusJS
apikey: # DisqusJS 向 API 发起请求时使用的 API Key
# Gitalk
# You can get yout ClientID and ClientSecret from https://github.com/settings/applications/new
# More info available at https://github.com/gitalk/gitalk#options
gitalk:
clientID: # GitHub Application Client ID
clientSecret: # GitHub Application Client Secret
repo: # The repo to store comments
owner: # GitHub repository owner. Can be personal user or organization.
admin: ['name'] # GitHub repo owner and collaborators, only these guys can initialize github issues, should be like ['admin'] or ['admin1','admin2']
id: location.pathname # The unique id of the page. Length must less than 50.
language: zh-CN # Localization language key, en, zh-CN and zh-TW are currently available.
labels: ['Gitalk'] # GitHub issue labels.
perPage: 10 # Pagination size, with maximum 100.
pagerDirection: last # Comment sorting direction, available values are last and first.
distractionFreeMode: false # Facebook-like distraction free mode.
createIssueManually: true # By default, Gitalk will create a corresponding github issue for your every single page automatically when the logined user is belong to the admin users. You can create it manually by setting this option to true.
# Valine
# 完整文档 https://valine.js.org/configuration.html
# 注意:下列配置项中的 true/false 不要用引号括起来
valine:
appid: # 从 LeanCloud 的应用中得到的 appId
appkey: # 从 LeanCloud 的应用中得到的 APP Key
placeholder: 说点什么 # 评论框占位提示符
path: window.location.pathname # 当前文章页路径,用于区分不同的文章页,以保证正确读取该文章页下的评论列表
avatar: retro # Gravatar 头像展示方式
meta: ['nick', 'mail', 'link'] # 评论者相关属性
pageSize: 10 # 评论列表分页,每页条数
lang: zh-CN # zh-CN | zh-TW | en | ja
highlight: false # 代码高亮
recordIP: false # 是否记录评论者IP
serverURLs: # REST API 服务器地址,国际版不填
# 畅言
# http://changyan.kuaizhan.com/
changyan:
appid: ''
appkey: ''
# Livere 来必力
# You can get your uid from https://www.livere.com/my_Livere
livere:
uid: ''
# Remark42
# https://remark42.com/
remark42:
host: https://remark.haoyizebo.com
site_id: haoyizebo
max_shown_comments: 10
locale: zh
#---------------------------
# 归档页
# Archive Page
#---------------------------
archive:
banner_img: /img/default.png
banner_img_height: 60 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
subtitle: # 打字机内容
#---------------------------
# 分类归档页
# Categories Page
#---------------------------
category:
banner_img: /img/default.png
banner_img_height: 60 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
subtitle: # 打字机内容
post_limit: 10 # 单个分类中折叠展示文章数的最大值,超过限制会显示 More
order_by: '-length' # 排序字段前面带减号是倒序不带减号是正序可选项name | length
collapse_depth: 0 # 层级的折叠深度0 是全部折叠,大于 0 后如果存在子分类则默认展开
#---------------------------
# 标签归档页
# Tags Page
#---------------------------
tag:
banner_img: /img/default.png
banner_img_height: 80 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
subtitle: # 打字机内容
tagcloud: # 标签云
min_font: 15
max_font: 30
unit: px # 字号单位
start_color: "#BBBBEE"
end_color: "#337ab7"
#---------------------------
# 关于页
# About Page
#---------------------------
about: # 关于页需要手动创建具体请见https://hexo.fluid-dev.com/docs/guide/#%E5%85%B3%E4%BA%8E%E9%A1%B5
banner_img: /img/default.png
banner_img_height: 60 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
subtitle: # 打字机内容
avatar: /img/avatar.png # 头像
name: myname
introduce: '一句简短的介绍' # 支持 HTML
icons: # 更多图标可从 https://hexo.fluid-dev.com/docs/icon/ 查找class 代表图标的 css class
- { class: 'iconfont icon-github-fill', link: 'https://github.com', tip: 'GitHub' }
- { class: 'iconfont icon-douban-fill', link: 'https://douban.com', tip: '豆瓣' }
- { class: 'iconfont icon-wechat-fill', qrcode: '/img/favicon.png' } # 添加 qrcode 后,点击不再跳转,而是悬浮二维码,需要指定 image
#---------------------------
# 404页
# 404 Page
#---------------------------
page404:
banner_img: /img/default.png
banner_img_height: 85 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
subtitle: 'Page not found' # 打字机内容
#---------------------------
# 友链页
# Links Page
#---------------------------
links:
banner_img: /img/default.png
banner_img_height: 60 # available: 0 - 100
banner_mask_alpha: 0.3 # available: 0 - 1.0
subtitle: # 打字机内容
items: # intro 与 image 可省略
- {
title: 'Fluid Blog',
intro: '主题博客',
link: 'https://hexo.fluid-dev.com/',
image: '/img/favicon.png'
}
- {
title: 'Fluid Docs',
intro: '主题使用指南',
link: 'https://hexo.fluid-dev.com/docs/',
image: '/img/favicon.png'
}
- {
title: 'Fluid Repo',
intro: '主题 GitHub 仓库',
link: 'https://github.com/fluid-dev/hexo-theme-fluid',
image: '/img/favicon.png'
}
#---------------------------
# 以下是配置 JS CSS 静态资源的 URL 前缀,可以自定义成 CDN 地址,
# 默认的 staticfile CDN 可能在部分地区无法访问,如果需要修改,最好使用与默认配置相同的版本,以避免潜在的问题,
# 在站点上启用 https 时,请使用 CDN 地址的 https 协议,
# ** 如果你不知道如何设置,请不要做任何改动 **
#
# Here is the url prefix to configure JS and CSS static assets. Set CDN addresses you want to customize.
# Be aware that you would better use the same version as default ones to avoid potential problems.
# Use the https protocol of CDN url when you enable https on your site.
# DO NOT EDIT THE FOLLOWING SETTINGS UNLESS YOU KNOW WHAT YOU ARE DOING
#---------------------------
static_prefix:
# 内部静态 Internal static
internal_js: /js
internal_css: /css
internal_img: /img
# 图标库,包含了大量社交类图标,主题依赖的不包含在内,因此可自行修改,详见 https://hexo.fluid-dev.com/docs/icon/
# Icon library, which includes many social icons, does not include those theme dependent, so your can modify link by yourself. Detail: https://hexo.fluid-dev.com/docs/en/icon/
iconfont: //at.alicdn.com/t/font_1736178_kmeydafke9r.css
anchor: https://cdn.staticfile.org/anchor-js/4.2.2/
github_markdown: https://cdn.staticfile.org/github-markdown-css/4.0.0/
jquery: https://cdn.staticfile.org/jquery/3.4.1/
bootstrap: https://cdn.staticfile.org/twitter-bootstrap/4.4.1/
highlightjs: https://cdn.staticfile.org/highlight.js/10.0.0/
prismjs: https://cdn.staticfile.org/prism/1.21.0/
tocbot: https://cdn.staticfile.org/tocbot/4.11.1/
typed: https://cdn.staticfile.org/typed.js/2.0.11/
fancybox: https://cdn.staticfile.org/fancybox/3.5.7/
mathjax: https://cdn.staticfile.org/mathjax/3.0.5/es5/
katex: https://cdn.staticfile.org/KaTeX/0.11.1/
busuanzi: https://busuanzi.ibruce.info/busuanzi/2.3/
clipboard: https://cdn.staticfile.org/clipboard.js/2.0.6/
mermaid: https://cdn.staticfile.org/mermaid/8.5.0/
valine: https://cdn.staticfile.org/valine/1.4.14/
gitalk: https://cdn.staticfile.org/gitalk/1.6.2/
blueimp_md5: https://cdn.staticfile.org/blueimp-md5/2.13.0/
disqusjs: https://cdn.jsdelivr.net/npm/disqusjs@1.0/dist/
hint: /lib/hint/

View File

@ -1,49 +0,0 @@
const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const eslint = require('gulp-eslint');
const shell = require('gulp-shell');
const yaml = require('js-yaml');
gulp.task('lint', () => gulp.src([
'./source/js/**/*.js',
'./scripts/**/*.js'
]).pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError()));
gulp.task('lint:ejs', shell.task([
'ejslint ./layout/**/*.ejs'
]));
gulp.task('validate:config', cb => {
const themeConfig = fs.readFileSync(path.join(__dirname, '_config.yml'));
try {
yaml.safeLoad(themeConfig);
return cb();
} catch (error) {
return cb(new Error(error));
}
});
gulp.task('validate:languages', cb => {
const languagesPath = path.join(__dirname, 'languages');
const languages = fs.readdirSync(languagesPath);
const errors = [];
languages.forEach(lang => {
const languagePath = path.join(languagesPath, lang);
try {
yaml.safeLoad(fs.readFileSync(languagePath), {
filename: path.relative(__dirname, languagePath)
});
} catch (error) {
errors.push(error);
}
});
return errors.length === 0 ? cb() : cb(errors);
});
gulp.task('default', gulp.series('lint', 'lint:ejs', 'validate:config', 'validate:languages'));

View File

@ -1,44 +0,0 @@
search:
title: Suchen
keyword: Stichwort
status:
success: v
error: x
postTotal: Insgesamt %d Artikel.
paginator:
pre: Vorheriger
next: Nächster
post:
toc: TOC
pre: Vorheriger
next: Nächster
home:
title: Startseite
archive:
title: Archiv
subtitle: Archiv
tag:
title: Etiketten
subtitle: Etiketten
category:
title: Kategorie
subtitle: Kategorie
about:
title: Über mich
subtitle: Über mich
page404:
title: Die Seite wurde nicht gefunden
subtitle: Die Seite wurde nicht gefunden
links:
title: Weblinks
subtitle: Weblinks

View File

@ -1,44 +0,0 @@
search:
title: Search
keyword: keyword
status:
success: v
error: x
postTotal: "%d posts in total."
paginator:
pre: Previous
next: Next
post:
toc: TOC
pre: Previous
next: Next
home:
title: Home
archive:
title: Archives
subtitle: Archive
tag:
title: Tags
subtitle: Tag
category:
title: Categories
subtitle: Category
about:
title: About
subtitle: About
page404:
title: Page not found
subtitle: Oops, Page not found...
links:
title: Links
subtitle: Links

View File

@ -1,44 +0,0 @@
search:
title: 検索
keyword: キーワード
status:
success: v
error: x
postTotal: 合計 %d 件のポスト
paginator:
pre: 前のページ
next: 次のページ
post:
toc: ディレクトリ
pre: 前の記事
next: 次の記事
home:
title: ホーム
archive:
title: アーカイブ
subtitle: アーカイブ
tag:
title: タグ
subtitle: タグ
category:
title: カテゴリー
subtitle: カテゴリー
about:
title: 本ブログ情報 
subtitle: 本ブログ情報
page404:
title: ページが見つかりませんでした
subtitle: ページが見つかりませんでした
links:
title: リンク
subtitle: リンク

View File

@ -1,44 +0,0 @@
search:
title: 搜索
keyword: 关键词
status:
success: v
error: x
postTotal: 共计 %d 篇文章
paginator:
pre: 上一页
next: 下一页
post:
toc: 目录
pre: 上一篇
next: 下一篇
home:
title: 首页
archive:
title: 归档
subtitle: 归档
tag:
title: 标签
subtitle: 标签
category:
title: 分类
subtitle: 分类
about:
title: 关于
subtitle: 关于
page404:
title: 页面走丢啦~
subtitle: 页面走丢啦~
links:
title: 友链
subtitle: 友情链接

View File

@ -1,16 +0,0 @@
<%
page.layout = "404"
page.title = theme.page404.title || __('page404.title')
page.subtitle = theme.page404.subtitle || __('page404.subtitle')
page.banner_img = theme.page404.banner_img
page.banner_img_height = theme.page404.banner_img_height
page.banner_mask_alpha = theme.page404.banner_mask_alpha
%>
<script>
function redirect() {
location.href = "/";
}
//setTimeout(redirect, 3000)
</script>

View File

@ -1,21 +0,0 @@
<% if(theme.footer.beian.enable) { %>
<!-- 备案信息 -->
<div class="beian">
<a href="http://beian.miit.gov.cn/" target="_blank"
rel="nofollow noopener"><%- theme.footer.beian.icp_text %></a>
<% if(theme.footer.beian.police_text && theme.footer.beian.police_code) { %>
<a
href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=<%- theme.footer.beian.police_code %>"
rel="nofollow noopener"
class="beian-police"
target="_blank"
>
<span class="beian-police-sep">&nbsp;|&nbsp;</span>
<% if(theme.footer.beian.police_icon) { %>
<img src="<%- url_for(theme.footer.beian.police_icon) %>" alt="police-icon" />
<% } %>
<span><%- theme.footer.beian.police_text %></span>
</a>
<% } %>
</div>
<% } %>

View File

@ -1,21 +0,0 @@
<% if(theme.changyan.appid){ %>
<div id="SOHUCS" sid='<%= page.permalink %>'></div>
<script type="text/javascript">
function loadChangyan() {
var appid = '<%= theme.changyan.appid %>';
var conf = '<%= theme.changyan.appkey %>';
var width = window.innerWidth || document.documentElement.clientWidth;
if (width < 960) {
window.document.write('<script id="changyan_mobile_js" charset="utf-8" type="text/javascript" src="http://changyan.sohu.com/upload/mobile/wap-js/changyan_mobile.js?client_id=' + appid + '&conf=' + conf + '"><\/script>');
} else {
addScript("https://changyan.sohu.com/upload/changyan.js", function() {
window.changyan.api.config({
appid: appid,
conf: conf
})
});
}
}
waitElementVisible('SOHUCS', loadChangyan)
</script>
<% } %>

View File

@ -1,43 +0,0 @@
<% if (theme.disqus.disqusjs) { %>
<div class="disqus" style="width:100%">
<div id="disqus_thread"></div>
<script>
function loadDisqus() {
addCssLink('<%= url_join(theme.static_prefix.disqusjs, 'disqusjs.css') %>');
addScript('<%= url_join(theme.static_prefix.disqusjs, 'disqus.js') %>', function () {
new DisqusJS({
shortname: '<%= theme.disqus.shortname %>',
apikey: '<%= theme.disqus.apikey %>'
});
});
}
waitElementVisible('disqus_thread', loadDisqus);
</script>
<noscript>Please enable JavaScript to view the
<a href="https://disqus.com/?ref_noscript" rel="nofollow noopener">comments powered by Disqus.</a>
</noscript>
</div>
<% } else { %>
<div class="disqus" style="width:100%">
<div id="disqus_thread"></div>
<script type="text/javascript">
var disqus_config = function () {
this.page.url = '<%= page.permalink %>';
this.page.identifier = '<%= url_for(page.path) %>';
};
function loadDisqus() {
(function () {
var d = document,
s = d.createElement('script');
s.src = '//' + '<%- theme.disqus.shortname %>' + '.disqus.com/embed.js';
s.setAttribute('data-timestamp', new Date());
(d.head || d.body).appendChild(s);
})();
}
waitElementVisible('disqus_thread', loadDisqus);
</script>
<noscript>Please enable JavaScript to view the
<a href="https://disqus.com/?ref_noscript" rel="nofollow noopener">comments powered by Disqus.</a>
</noscript>
</div>
<% } %>

View File

@ -1,26 +0,0 @@
<% if(theme.gitalk.clientID && theme.gitalk.clientSecret && theme.gitalk.repo){ %>
<div id="gitalk-container"></div>
<script type="text/javascript">
function loadGitalk() {
addScript('<%= url_join(theme.static_prefix.blueimp_md5, 'js/md5.min.js') %>');
addScript('<%= url_join(theme.static_prefix.gitalk, 'gitalk.min.js') %>', function () {
var gitalk = new Gitalk({
clientID: '<%= theme.gitalk.clientID %>',
clientSecret: '<%= theme.gitalk.clientSecret %>',
repo: '<%= theme.gitalk.repo %>',
owner: '<%= theme.gitalk.owner %>',
admin: <%- JSON.stringify(theme.gitalk.admin || []) %>,
id: md5(<%= theme.gitalk.id %>),
language: '<%= theme.gitalk.language %>',
labels: <%- JSON.stringify(theme.gitalk.labels || []) %>,
perPage: <%= theme.gitalk.perPage %>,
pagerDirection: '<%= theme.gitalk.pagerDirection %>',
createIssueManually: <%= theme.gitalk.createIssueManually %>,
distractionFreeMode: <%= theme.gitalk.distractionFreeMode %>
});
gitalk.render('gitalk-container');
});
}
waitElementVisible('gitalk-container', loadGitalk);
</script>
<% } %>

View File

@ -1,11 +0,0 @@
<% if(theme.livere.uid){ %>
<div id="lv-container" data-id="city" data-uid="<%= theme.livere.uid %>">
<script type="text/javascript">
function loadLivere() {
addScript('https://cdn-city.livere.com/js/embed.dist.js');
}
waitElementVisible('lv-container', loadLivere);
</script>
<noscript>为正常使用来必力评论功能请允许 JavaScript 运行</noscript>
</div>
<% } %>

View File

@ -1,32 +0,0 @@
<% if(theme.remark42.host && theme.remark42.site_id){ %>
<div id="remark42"></div>
<script type="text/javascript">
var schema = document.documentElement.getAttribute('data-user-color-scheme');
if (schema !== 'light' && schema !== 'dark') {
schema = 'light';
}
var remark_config = {
host: '<%= theme.remark42.host %>',
site_id: '<%= theme.remark42.site_id %>',
components: ['embed'],
url: '<%= url_for(page.path) %>',
max_shown_comments: '<%= theme.remark42.max_shown_comments %>',
theme: schema,
page_title: '<%= page.title %>',
locale: '<%= theme.remark42.locale %>'
};
function loadRemark42() {
(function (c) {
for (var i = 0; i < c.length; i++) {
var d = document, s = d.createElement('script');
s.src = remark_config.host + '/web/' + c[i] + '.js';
s.defer = true;
(d.head || d.body).appendChild(s);
}
})(remark_config.components || [ 'embed' ]);
}
waitElementVisible('remark42', loadRemark42);
</script>
<% } %>

View File

@ -1,27 +0,0 @@
<% if(theme.utterances.repo && theme.utterances.issue_term){ %>
<script type="text/javascript">
function loadUtterances() {
var light = '<%= theme.utterances.theme || 'github-light' %>';
var dark = '<%= theme.utterances.theme_dark || 'github-dark' %>';
var schema = document.documentElement.getAttribute('data-user-color-scheme');
if (schema === 'dark') {
schema = dark;
} else {
schema = light;
}
window.UtterancesThemeLight = light;
window.UtterancesThemeDark = dark;
var s = document.createElement('script');
s.setAttribute('src', 'https://utteranc.es/client.js');
s.setAttribute('repo', '<%= theme.utterances.repo %>');
s.setAttribute('issue-term', '<%= theme.utterances.issue_term %>');
<% if (theme.utterances.label) { %>
s.setAttribute('label', '<%= theme.utterances.label %>');
<% } %>
s.setAttribute('theme', schema);
s.setAttribute('crossorigin', '<%= theme.utterances.crossorigin %>');
document.getElementById('comments').appendChild(s);
}
waitElementVisible('comments', loadUtterances)
</script>
<% } %>

View File

@ -1,26 +0,0 @@
<% if(theme.valine.appid && theme.valine.appkey){ %>
<div id="vcomments"></div>
<script type="text/javascript">
function loadValine() {
addScript('<%= url_join(theme.static_prefix.valine, 'Valine.min.js') %>', function () {
new Valine({
el: "#vcomments",
app_id: "<%= theme.valine.appid %>",
app_key: "<%= theme.valine.appkey %>",
placeholder: "<%= theme.valine.placeholder %>",
path: <%= theme.valine.path %>,
avatar: "<%= theme.valine.avatar %>",
meta: <%- JSON.stringify(theme.valine.meta || []) %>,
pageSize: "<%= theme.valine.pageSize %>",
lang: "<%= theme.valine.lang %>",
highlight: <%= theme.valine.highlight %>,
recordIP: <%= theme.valine.recordIP %>,
serverURLs: "<%= theme.valine.serverURLs %>",
});
});
}
waitElementVisible('vcomments', loadValine);
</script>
<noscript>Please enable JavaScript to view the <a href="https://valine.js.org" rel="nofollow noopener">comments
powered by Valine.</a></noscript>
<% } %>

View File

@ -1,44 +0,0 @@
<%- css_ex(theme.static_prefix.bootstrap, 'css/bootstrap.min.css') %>
<% if (is_post() || is_page()) { %>
<%- css_ex(theme.static_prefix.github_markdown, 'github-markdown.min.css') %>
<%- css_ex(theme.static_prefix.hint, 'hint.min.css') %>
<% if (theme.code.highlight.enable) { %>
<% var cssName %>
<% if (theme.code.highlight.lib === 'highlightjs') { %>
<% cssName = theme.code.highlight.highlightjs.style.toLowerCase().replace(/(?<!([0-9]))\s(?!([0-9]))/g, '-').replace(/\s/g, '') %>
<%- css_ex(theme.static_prefix.highlightjs, `/styles/${ cssName }.min.css`) %>
<% } else if (theme.code.highlight.lib === 'prismjs') { %>
<% var style = theme.code.highlight.prismjs.style %>
<% if (!style || style === 'default') { %>
<% cssName = '' %>
<% } else { %>
<% cssName = style.toLowerCase().replace(/[\s\-]/g, '') %>
<% if (cssName === 'prism') { cssName = '' } %>
<% if (cssName === 'tomorrownight') { cssName = 'tomorrow' } %>
<% } %>
<%- css_ex(theme.static_prefix.prismjs, `/themes/${ cssName ? 'prism-' + cssName : 'prism' }.min.css`) %>
<% if (theme.code.highlight.prismjs.line_number) { %>
<%- css_ex(theme.static_prefix.prismjs, '/plugins/line-numbers/prism-line-numbers.min.css') %>
<% } %>
<% } %>
<% } %>
<% if(page.comments && theme.post.comments.enable && theme.post.comments.type === 'gitalk' &&
theme.gitalk.clientID && theme.gitalk.clientSecret && theme.gitalk.repo){ %>
<%- css_ex(theme.static_prefix.internal_css, 'gitalk.css') %>
<% } %>
<% } %>
<!-- 主题依赖的图标库,不要自行修改 -->
<%- css('//at.alicdn.com/t/font_1749284_ba1fz6golrf.css') %>
<%- css(theme.static_prefix.iconfont) %>
<%- css_ex(theme.static_prefix.internal_css, 'main.css') %>
<!-- 自定义样式保持在最底部 -->
<% if (theme.custom_css) { %>
<%- css(theme.custom_css) %>
<% } %>

View File

@ -1,14 +0,0 @@
<footer class="text-center mt-5 py-3">
<div class="footer-content">
<%- theme.footer.content %>
</div>
<%- partial('_partial/statistics.ejs') %>
<%- partial('_partial/beian.ejs') %>
<% if(theme.web_analytics.cnzz) { %>
<!-- cnzz Analytics Icon -->
<span id="cnzz_stat_icon_<%- theme.web_analytics.cnzz %>" style="display: none"></span>
<% } %>
</footer>
<!-- SCRIPTS -->
<%- partial('_partial/scripts.ejs') %>

View File

@ -1,28 +0,0 @@
<%
var joinStr = theme.title_join_string
var title = config.title
if (page.title) {
title = [page.title, title].join(joinStr)
}
%>
<head>
<meta charset="UTF-8">
<link rel="apple-touch-icon" sizes="76x76" href="<%- url_for(theme.apple_touch_icon) %>">
<link rel="icon" type="image/png" href="<%- url_for(theme.favicon) %>">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<% if (theme.force_https) { %>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
<% } %>
<meta name="theme-color" content="<%- theme.color.navbar_bg_color %>">
<meta name="description" content="<%= config.description %>">
<meta name="author" content="<%= page.author || config.author %>">
<meta name="keywords" content="<%= config.keywords %>">
<title><%= title %></title>
<%- partial('_partial/css.ejs') %>
<%- js_ex(theme.static_prefix.internal_js, 'utils.js') %>
<%- js_ex(theme.static_prefix.internal_js, 'color-schema.js') %>
</head>

View File

@ -1,65 +0,0 @@
<nav id="navbar" class="navbar fixed-top navbar-expand-lg navbar-dark scrolling-navbar">
<div class="container">
<a class="navbar-brand"
href="<%- url_for() %>">&nbsp;<strong><%- theme.navbar.blog_title || config.title %></strong>&nbsp;</a>
<button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<div class="animated-icon"><span></span><span></span><span></span></div>
</button>
<!-- Collapsible content -->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto text-center">
<% for(const each of theme.navbar.menu || []) { %>
<% if (!each.submenu && !each.link) continue %>
<% var text = each.name || __(each.key + '.title') %>
<% if (text.indexOf('.title') !== -1) {
text = each.key
} %>
<% if (each.submenu) { %>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<%- each.icon ? '<i class="' + each.icon + '"></i>' : '' %>
<%- text %>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<% for(const subEach of each.submenu || []) { %>
<% if (!subEach.link) continue %>
<% var subText = subEach.name || __(subEach.key + '.title') %>
<% if (subText.indexOf('.title') !== -1) {
subText = subEach.key
} %>
<a class="dropdown-item" href="<%= url_for(subEach.link) %>">
<%- subEach.icon ? '<i class="' + subEach.icon + '"></i>' : '' %>
<%- subText %>
</a>
<% } %>
</div>
</li>
<% } else { %>
<li class="nav-item">
<a class="nav-link" href="<%= url_for(each.link) %>">
<%- each.icon ? '<i class="' + each.icon + '"></i>' : '' %>
<%- text %>
</a>
</li>
<% } %>
<% } %>
<% if(theme.search.enable) { %>
<li class="nav-item" id="search-btn">
<a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
class="iconfont icon-search"></i>&nbsp;</a>
</li>
<% } %>
<% if(theme.dark_mode && theme.dark_mode.enable) { %>
<li class="nav-item" id="color-toggle-btn">
<a class="nav-link" href="javascript:">&nbsp;<i
class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
</li>
<% } %>
</ul>
</div>
</div>
</nav>

View File

@ -1,18 +0,0 @@
<% if (page.total > 1){ %>
<nav aria-label="navigation">
<span class="pagination" id="pagination">
<%- paginator({
prev_text: '<i class="iconfont icon-arrowleft"></i>',
next_text: '<i class="iconfont icon-arrowright"></i>',
mid_size: 2,
escape: false
}) %>
</span>
</nav>
<% var point = theme.scroll_down_arrow.scroll_after_turning_page ? '#board' : '' %>
<script>
for (ele of document.getElementById("pagination").getElementsByTagName("a")) {
ele.href += '<%- point %>';
}
</script>
<% } %>

View File

@ -1,66 +0,0 @@
<% if (theme.web_analytics.enable) { %>
<% if(theme.web_analytics.baidu) { %>
<!-- Baidu Analytics -->
<script defer>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?<%= theme.web_analytics.baidu %>";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<% } %>
<% if (theme.web_analytics.google){ %>
<!-- Google Analytics -->
<script defer>
window.ga = window.ga || function () { (ga.q = ga.q || []).push(arguments) };
ga.l = +new Date;
ga('create', '<%= theme.web_analytics.google %>', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<% } %>
<% if (theme.web_analytics.gtag){ %>
<!-- Google gtag.js -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<%- theme.web_analytics.gtag %>"></script>
<script defer>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<%- theme.web_analytics.gtag %>');
</script>
<% } %>
<% if(theme.web_analytics.tencent && theme.web_analytics.tencent.sid && theme.web_analytics.tencent.cid) { %>
<!-- Tencent Analytics -->
<script defer>
var _mtac = {};
(function () {
var mta = document.createElement("script");
mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4";
mta.setAttribute("name", "MTAH5");
mta.setAttribute("sid", "<%= theme.web_analytics.tencent.sid %>");
<% if(theme.web_analytics.tencent.cid) { %>
mta.setAttribute("cid", "<%= theme.web_analytics.tencent.cid %>");
<% } %>
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(mta, s);
})();
</script>
<% } %>
<% if(theme.web_analytics.woyaola) { %>
<!-- 51.la Analytics -->
<script defer type="text/javascript" src="//js.users.51.la/<%= theme.web_analytics.woyaola %>.js"></script>
<% } %>
<% if(theme.web_analytics.cnzz) { %>
<!-- cnzz Analytics -->
<script defer src="//s4.cnzz.com/z_stat.php?id=<%- theme.web_analytics.cnzz %>&show=pic"
type="text/javascript"></script>
<% } %>
<% } %>

View File

@ -1,18 +0,0 @@
<% if((is_post() || is_page()) && theme.fun_features.anchorjs.enable){ %>
<%- js_ex(theme.static_prefix.anchor, "/anchor.min.js") %>
<script>
anchors.options = {
placement: "<%- theme.fun_features.anchorjs.placement %>",
visible: "<%- theme.fun_features.anchorjs.visible %>",
<% if(theme.fun_features.anchorjs.icon != ""){ %>
icon: "<%- theme.fun_features.anchorjs.icon %>"
<% } %>
};
var el = "<%- theme.fun_features.anchorjs.element || 'h1,h2,h3,h4,h5,h6' %>".split(",");
var res = [];
for (item of el) {
res.push(".markdown-body > " + item)
}
anchors.add(res.join(", "))
</script>
<% } %>

View File

@ -1,15 +0,0 @@
<% if ((is_post() || (is_page() && page.image_zoom)) && theme.post.image_zoom.enable) { %>
<%- js_ex(theme.static_prefix.fancybox, 'jquery.fancybox.min.js') %>
<%- css_ex(theme.static_prefix.fancybox, 'jquery.fancybox.min.css') %>
<script>
$('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
function () {
var element = document.createElement('a');
$(element).attr('data-fancybox', 'images');
$(element).attr('href', $(this).attr('src'));
$(this).wrap(element);
}
);
</script>
<% } %>

View File

@ -1,178 +0,0 @@
<script defer>
(function () {
// 查询存储的记录
function getRecord(Counter, target) {
return new Promise(function (resolve, reject) {
Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({target})))
.then(resp => resp.json())
.then(({results, code, error}) => {
if (code === 401) {
throw error;
}
if (results && results.length > 0) {
var record = results[0];
resolve(record);
} else {
Counter('post', '/classes/Counter', {target, time: 0})
.then(resp => resp.json())
.then((record, error) => {
if (error) {
throw error;
}
resolve(record);
}).catch(error => {
console.error('Failed to create', error);
reject(error);
});
}
}).catch((error) => {
console.error('LeanCloud Counter Error:', error);
reject(error);
});
})
}
// 发起自增请求
function increment(Counter, incrArr) {
return new Promise(function (resolve, reject) {
Counter('post', '/batch', {
"requests": incrArr
}).then((res) => {
res = res.json();
if (res.error) {
throw res.error;
}
resolve(res);
}).catch((error) => {
console.error('Failed to save visitor count', error);
reject(error);
});
});
}
// 构建自增请求体
function buildIncrement(objectId) {
return {
"method": "PUT",
"path": `/1.1/classes/Counter/${ objectId }`,
"body": {
"time": {
'__op': 'Increment',
'amount': 1
}
}
}
}
// 校验是否为有效的 UV
function validUV() {
var key = 'LeanCloud_UV_Flag';
var flag = localStorage.getItem(key);
if (flag) {
// 距离标记小于 24 小时则不计为 UV
if (new Date().getTime() - parseInt(flag) <= 86400000) {
return false;
}
}
localStorage.setItem(key, new Date().getTime().toString());
return true;
}
function addCount(Counter) {
var enableIncr = '<%= theme.web_analytics.enable %>' === 'true' && window.location.hostname !== 'localhost';
var getterArr = [];
var incrArr = [];
// 请求 PV 并自增
var pvCtn = document.querySelector('#leancloud-site-pv-container');
if (pvCtn || enableIncr) {
var pvGetter = getRecord(Counter, 'site-pv').then((record) => {
incrArr.push(buildIncrement(record.objectId))
var ele = document.querySelector('#leancloud-site-pv');
if (ele) {
ele.innerText = record.time + 1;
if (pvCtn) {
pvCtn.style.display = 'inline';
}
}
});
getterArr.push(pvGetter);
}
// 请求 UV 并自增
var uvCtn = document.querySelector('#leancloud-site-uv-container');
if (uvCtn || enableIncr) {
var uvGetter = getRecord(Counter, 'site-uv').then((record) => {
var vuv = validUV();
vuv && incrArr.push(buildIncrement(record.objectId))
var ele = document.querySelector('#leancloud-site-uv');
if (ele) {
ele.innerText = record.time + (vuv ? 1 : 0);
if (uvCtn) {
uvCtn.style.display = 'inline';
}
}
});
getterArr.push(uvGetter);
}
// 如果是文章,请求文章的浏览数,并自增
if ('<%= is_post() %>' === 'true') {
var viewCtn = document.querySelector('#leancloud-post-views-container');
if (viewCtn || enableIncr) {
var target = decodeURI('<%= url_for(page.path) %>');
var viewGetter = getRecord(Counter, target).then((record) => {
incrArr.push(buildIncrement(record.objectId))
if (viewCtn) {
var ele = document.querySelector('#leancloud-post-views');
if (ele) {
ele.innerText = (record.time || 0) + 1;
viewCtn.style.display = 'inline';
}
}
});
getterArr.push(viewGetter);
}
}
// 如果启动计数自增,批量发起自增请求
if (enableIncr) {
Promise.all(getterArr).then(() => {
incrArr.length > 0 && increment(Counter, incrArr);
})
}
}
var app_id = '<%= theme.web_analytics.leancloud.app_id %>'
var app_key = '<%= theme.web_analytics.leancloud.app_key %>'
var server_url = '<%= theme.web_analytics.leancloud.server_url %>'
function fetchData(api_server) {
var Counter = (method, url, data) => {
return fetch(`${ api_server }/1.1${ url }`, {
method,
headers: {
'X-LC-Id': app_id,
'X-LC-Key': app_key,
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
};
addCount(Counter);
}
var api_server = app_id.slice(-9) !== '-MdYXbMMI' ? server_url : `https://${ app_id.slice(0, 8).toLowerCase() }.api.lncldglobal.com`;
if (api_server) {
fetchData(api_server);
} else {
fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id)
.then(resp => resp.json())
.then(({api_server}) => {
fetchData('https://' + api_server);
});
}
})();
</script>

View File

@ -1,11 +0,0 @@
<% if(theme.search.enable){ %>
<%- js_ex(theme.static_prefix.internal_js, "local-search.js") %>
<script>
var path = "<%- url_for(theme.search.path) || '/local-search.xml' %>";
var inputArea = document.querySelector("#local-search-input");
inputArea.onclick = function () {
searchFunc(path, 'local-search-input', 'local-search-result');
this.onclick = null
}
</script>
<% } %>

View File

@ -1,57 +0,0 @@
<%
var enable = theme.post.math.enable;
if (enable) {
if (is_post()) {
enable = !theme.post.math.specific || (theme.post.math.specific && page.math);
} else if (is_page()) {
enable = page.math;
} else {
enable = false;
}
}
%>
<% if (enable) { %>
<% var engine = theme.post.math.engine; %>
<% if(engine === 'mathjax') { %>
<!-- MathJax -->
<script>
MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']]
},
options: {
renderActions: {
findScript: [10, doc => {
document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
const display = !!node.type.match(/; *mode=display/);
const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
const text = document.createTextNode('');
node.parentNode.replaceChild(text, node);
math.start = { node: text, delim: '', n: 0 };
math.end = { node: text, delim: '', n: 0 };
doc.math.push(math);
});
}, '', false],
insertedScript: [200, () => {
document.querySelectorAll('mjx-container').forEach(node => {
let target = node.parentNode;
if (target.nodeName.toLowerCase() === 'li') {
target.parentNode.classList.add('has-jax');
}
});
}, '', false]
}
}
};
</script>
<%- js_ex(theme.static_prefix.mathjax, "tex-svg.js", 'async') %>
<% } else if (engine === 'katex') { %>
<!-- KaTeX -->
<%- css_ex(theme.static_prefix.katex, "katex.min.css") %>
<% } %>
<% } %>

View File

@ -1,24 +0,0 @@
<%
var enable = theme.post.mermaid.enable;
if (enable) {
if (is_post()) {
enable = !theme.post.mermaid.specific || (theme.post.mermaid.specific && page.mermaid);
} else if (is_page()) {
enable = page.mermaid;
} else {
enable = false;
}
}
var options = JSON.stringify(theme.post.mermaid.options);
%>
<% if (enable) { %>
<%- js_ex(theme.static_prefix.mermaid, 'mermaid.min.js') %>
<script>
if (window.mermaid) {
mermaid.initialize(<%- options %>);
}
</script>
<% } %>

View File

@ -1,26 +0,0 @@
<% if(is_post() && theme.post.toc.enable && page.toc != false){ %>
<%- js_ex(theme.static_prefix.tocbot, '/tocbot.min.js') %>
<script>
$(document).ready(function () {
var boardCtn = $('#board-ctn');
var boardTop = boardCtn.offset().top;
tocbot.init({
tocSelector: '#tocbot',
contentSelector: '#post-body',
headingSelector: '<%= theme.post.toc.headingSelector || "h1,h2,h3,h4,h5,h6" %>',
linkClass: 'tocbot-link',
activeLinkClass: 'tocbot-active-link',
listClass: 'tocbot-list',
isCollapsedClass: 'tocbot-is-collapsed',
collapsibleClass: 'tocbot-is-collapsible',
collapseDepth: <%= theme.post.toc.collapseDepth || 0 %>,
scrollSmooth: true,
headingsOffset: -boardTop
});
if ($('.toc-list-item').length > 0) {
$('#toc').css('visibility', 'visible');
}
});
</script>
<% } %>

View File

@ -1,19 +0,0 @@
<% if(theme.fun_features.typing.enable && page.subtitle !== false){ %>
<%- js_ex(theme.static_prefix.typed, "/typed.min.js") %>
<script>
var typed = new Typed('#subtitle', {
strings: [
' ',
"<%- data.subtitle %>&nbsp;",
],
cursorChar: "<%- theme.fun_features.typing.cursorChar %>",
typeSpeed: <%- theme.fun_features.typing.typeSpeed %>,
loop: <%- theme.fun_features.typing.loop %>,
});
typed.stop();
$(document).ready(function () {
$(".typed-cursor").addClass("h2");
typed.start();
});
</script>
<% } %>

View File

@ -1,54 +0,0 @@
<div class="mt-3">
<% if (theme.post.meta.author && theme.post.meta.author.enable && (page.author || config.author)) { %>
<span class="post-meta mr-2">
<i class="iconfont icon-author" aria-hidden="true"></i>
<%- page.author || config.author %>
</span>
<% } %>
<% if (theme.post.meta.date.enable) { %>
<span class="post-meta">
<i class="iconfont icon-date-fill" aria-hidden="true"></i>
<time datetime="<%= full_date(page.date, 'YYYY-MM-DD HH:mm') %>" pubdate>
<%= full_date(page.date, theme.post.meta.date.format) %>
</time>
</span>
<% } %>
</div>
<div class="mt-1">
<% if (theme.post.meta.wordcount.enable) { %>
<% var wordcount_texts = theme.post.meta.wordcount.format.split('{}') %>
<span class="post-meta mr-2">
<i class="iconfont icon-chart"></i>
<%- wordcount_texts[0] %><%- wordcount(page.content) %><%- wordcount_texts[1] %>
</span>
<% } %>
<% if (theme.post.meta.min2read.enable) { %>
<% var min2read_texts = theme.post.meta.min2read.format.split('{}') %>
<span class="post-meta mr-2">
<i class="iconfont icon-clock-fill"></i>
<% var words = parseInt(theme.post.meta.min2read.words) %>
<%- min2read_texts[0] %>
<%- min2read(page.content, {cn: words, en: words / 2}) %>
<%- min2read_texts[1] %>
</span>
<% } %>
<% var views_texts = theme.post.meta.views.format.split('{}') %>
<% if (theme.post.meta.views.enable) { %>
<% if (theme.post.meta.views.source === 'leancloud') { %>
<!-- LeanCloud 统计文章PV -->
<span id="leancloud-post-views-container" class="post-meta" style="display: none">
<i class="iconfont icon-eye" aria-hidden="true"></i>
<%- views_texts[0] %><span id="leancloud-post-views"></span><%- views_texts[1] %>
</span>
<% } else if (theme.post.meta.views.source === 'busuanzi') { %>
<!-- 不蒜子统计文章PV -->
<span id="busuanzi_container_page_pv" style="display: none">
<i class="iconfont icon-eye" aria-hidden="true"></i>
<%- views_texts[0] %><span id="busuanzi_value_page_pv"></span><%- views_texts[1] %>
</span>
<% } %>
<% } %>
</div>

View File

@ -1,57 +0,0 @@
<%- js_ex(theme.static_prefix.jquery, 'jquery.min.js') %>
<%- js_ex(theme.static_prefix.bootstrap, 'js/bootstrap.min.js') %>
<%- js_ex(theme.static_prefix.internal_js, 'debouncer.js') %>
<%- js_ex(theme.static_prefix.internal_js, 'main.js') %>
<!-- Plugins -->
<% if (theme.lazyload.enable){ %>
<% if (theme.lazyload.onlypost) { %>
<% if (is_post() || is_page()) { %>
<%- js_ex(theme.static_prefix.internal_js, 'lazyload.js') %>
<% } %>
<% } else { %>
<%- js_ex(theme.static_prefix.internal_js, 'lazyload.js') %>
<% }%>
<% } %>
<% if (theme.code.highlight.enable) { %>
<% if (theme.code.highlight.lib === 'prismjs') { %>
<% if (!theme.code.highlight.prismjs.preprocess) { %>
<%- js_ex(theme.static_prefix.prismjs, 'components/prism-core.min.js') %>
<%- js_ex(theme.static_prefix.prismjs, 'plugins/autoloader/prism-autoloader.min.js') %>
<% if (theme.code.highlight.prismjs.line_number) { %>
<%- js_ex(theme.static_prefix.prismjs, '/plugins/line-numbers/prism-line-numbers.min.js') %>
<% } %>
<% } %>
<% } %>
<% } %>
<% if (theme.code.copy_btn) { %>
<%- js_ex(theme.static_prefix.clipboard, 'clipboard.min.js', 'defer') %>
<%- js_ex(theme.static_prefix.internal_js, 'clipboard-use.js') %>
<% } %>
<% if ((theme.footer.statistics.enable && theme.footer.statistics.source === 'busuanzi')
|| (page.meta !== false && theme.post.meta.views.enable && theme.post.meta.views.source === 'busuanzi')) { %>
<%- js_ex(theme.static_prefix.busuanzi, 'busuanzi.pure.mini.js', 'defer') %>
<% } else if ( theme.web_analytics.leancloud.app_id && theme.web_analytics.leancloud.app_key &&
((theme.footer.statistics.enable && theme.footer.statistics.source === 'leancloud')
|| (page.meta !== false && theme.post.meta.views.enable && theme.post.meta.views.source === 'leancloud'))) { %>
<%- partial('_partial/plugins/leancloud.ejs') %>
<% } else if (theme.web_analytics.enable && theme.web_analytics.leancloud.app_id && theme.web_analytics.leancloud.app_key) { %>
<%- partial('_partial/plugins/leancloud.ejs') %>
<% } %>
<% if (theme.custom_js) { %>
<%- js(theme.custom_js) %>
<% } %>
<%- partial('_partial/plugins/tocjs.ejs') %>
<%- partial('_partial/plugins/typed.ejs') %>
<%- partial('_partial/plugins/anchor.ejs') %>
<%- partial('_partial/plugins/local-search.ejs') %>
<%- partial('_partial/plugins/fancybox.ejs') %>
<%- partial('_partial/plugins/math.ejs') %>
<%- partial('_partial/plugins/mermaid.ejs') %>
<%- partial('_partial/plugins/analytics.ejs') %>

View File

@ -1,21 +0,0 @@
<div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content">
<div class="modal-header text-center">
<h4 class="modal-title w-100 font-weight-bold"><%= __('search.title') %></h4>
<button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body mx-3">
<div class="md-form mb-5">
<input type="text" id="local-search-input" class="form-control validate">
<label data-error="<%= __('search.status.error') %>" data-success="<%= __('search.status.success') %>"
for="local-search-input"><%= __('search.keyword') %></label>
</div>
<div class="list-group" id="local-search-result"></div>
</div>
</div>
</div>
</div>

View File

@ -1,43 +0,0 @@
<% if (theme.footer.statistics.enable) { %>
<div class="statistics">
<% var pv_texts = theme.footer.statistics.pv_format.split('{}') %>
<% var uv_texts = theme.footer.statistics.uv_format.split('{}') %>
<% if (theme.footer.statistics.source === 'leancloud') { %>
<% if (theme.footer.statistics.pv_format) { %>
<!-- LeanCloud 统计PV -->
<span id="leancloud-site-pv-container" style="display: none">
<%- pv_texts[0] %>
<span id="leancloud-site-pv"></span>
<%- pv_texts[1] %>
</span>
<% } %>
<% if (theme.footer.statistics.uv_format) { %>
<!-- LeanCloud 统计UV -->
<span id="leancloud-site-uv-container" style="display: none">
<%- uv_texts[0] %>
<span id="leancloud-site-uv"></span>
<%- uv_texts[1] %>
</span>
<% } %>
<% } else if (theme.footer.statistics.source === 'busuanzi') { %>
<% if (theme.footer.statistics.pv_format) { %>
<!-- 不蒜子统计PV -->
<span id="busuanzi_container_site_pv" style="display: none">
<%- pv_texts[0] %>
<span id="busuanzi_value_site_pv"></span>
<%- pv_texts[1] %>
</span>
<% } %>
<% if (theme.footer.statistics.uv_format) { %>
<!-- 不蒜子统计UV -->
<span id="busuanzi_container_site_uv" style="display: none">
<%- uv_texts[0] %>
<span id="busuanzi_value_site_uv"></span>
<%- uv_texts[1] %>
</span>
<% } %>
<% } %>
</div>
<% } %>

View File

@ -1,4 +0,0 @@
<div id="toc">
<p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;<%= __('post.toc') %></p>
<div id="tocbot"></div>
</div>

View File

@ -1,34 +0,0 @@
<%
page.layout = "about"
page.title = theme.about.title || __('about.title')
page.subtitle = theme.about.subtitle || __('about.subtitle')
page.banner_img = theme.about.banner_img
page.banner_img_height = theme.about.banner_img_height
page.banner_mask_alpha = theme.about.banner_mask_alpha
%>
<div class="text-center">
<div class="about-info">
<div class="about-name"><%- theme.about.name %></div>
<div class="about-intro"><%- theme.about.introduce %></div>
<div class="about-icons">
<% for(const each of theme.about.icons || []) { %>
<% if (!each.class) continue; %>
<% var cls = each.class %>
<% var isQr = each.qrcode %>
<a href="<%= isQr ? 'javascript:;' : url_for(each.link) %>" class="<%= isQr ? 'qr-trigger' : '' %>
<%= !isQr && each.tip ? 'hint--bottom hint--rounded' : '' %>"
<%= !isQr && each.tip ? 'aria-label=' + each.tip : '' %>
>
<i class="<%= cls %>" aria-hidden="true"></i>
<% if (isQr) { %>
<img class="qr-img" src="<%= url_for(each.qrcode) %>" alt="qrcode" />
<% } %>
</a>
<% } %>
</div>
</div>
</div>
<div class="mt-5 markdown-body">
<%- page.content %>
</div>

View File

@ -1,25 +0,0 @@
<%
page.layout = "archive"
page.title = theme.archive.title || __('archive.title')
page.subtitle = theme.archive.subtitle || __('archive.subtitle')
page.banner_img = theme.archive.banner_img
page.banner_img_height = theme.archive.banner_img_height
page.banner_mask_alpha = theme.archive.banner_mask_alpha
var date_cursor = 'xxx'
%>
<div class="list-group">
<p class="h4"><%= __('postTotal', site.posts.length) %></p>
<hr>
<% page.posts.each(function (post) { %>
<% if(date(post.date, "YYYY") != date_cursor) { %>
<% date_cursor = date(post.date, "YYYY") %>
<p class="h5"><%= date_cursor %></p>
<% } %>
<a href="<%- url_for(post.path) %>" class="list-group-item list-group-item-action">
<span class="archive-post-title"><%= post.title %></span>
<time style="float: right;"><%- date(post.date, "MM-DD") %></time>
</a>
<% }) %>
</div>
<%- partial('_partial/paginator') %>

View File

@ -1,72 +0,0 @@
<%
page.layout = "categories"
page.title = theme.category.title || __('category.title')
page.subtitle = theme.category.subtitle || __('category.subtitle')
page.banner_img = theme.category.banner_img
page.banner_img_height = theme.category.banner_img_height
page.banner_mask_alpha = theme.category.banner_mask_alpha
var orderBy = theme.category.order_by || 'name'
%>
<% function render_categories(cats, depth) { %>
<% depth = depth || 0 %>
<% return cats.each(function(cat){ %>
<% var subCats = site.categories.find({parent: cat._id}).sort(orderBy).filter(cat => cat.length) %>
<% var collapsed = subCats.length === 0 || depth >= theme.category.collapse_depth %>
<div class="<%= depth <= 0 ? 'category' : 'category-sub' %> row">
<a
class="<%= depth <= 0 ? 'category-item' : 'category-subitem' %> <%= collapsed ? 'collapsed' : '' %> list-group-item category-item-action col-10 col-md-11"
id="heading-<%= cat._id %>" role="tab" data-toggle="collapse" href="#collapse-<%= cat._id %>"
aria-expanded="<%= collapsed ? 'false' : 'true' %>"
>
<%= cat.name %>
<i class="iconfont icon-arrowright"></i>
</a>
<a href="<%= url_for(cat.path) %>" class="category-count col-2 col-md-1">
<i class="iconfont icon-articles"></i>
<span><%= cat.posts.length %></span>
</a>
<div class="category-collapse">
<% if (subCats.length > 0) { %>
<%- render_sub_categories(subCats, cat, depth + 1, !collapsed) %>
<% } else { %>
<%- render_posts(cat) %>
<% } %>
</div>
</div>
<% }) %>
<% } %>
<% function render_sub_categories(cats, parent, depth, show) { %>
<div id="collapse-<%= parent._id %>" class="collapse in <%= show ? 'show' : '' %>" role="tabpanel"
aria-labelledby="heading-<%= parent._id %>">
<%- render_categories(cats, depth) %>
</div>
<% } %>
<% function render_posts(cat) { %>
<div id="collapse-<%= cat._id %>" class="collapse in" role="tabpanel"
aria-labelledby="heading-<%= cat._id %>">
<% var limit = theme.category.post_limit %>
<% var posts = cat.posts.sort(config.index_generator.order_by || '-date') %>
<% for (var idx = 0; idx < posts.length; idx++) { %>
<% var post = posts.data[idx] %>
<% if (idx && limit && idx >= limit) { %>
<a href="<%- url_for(cat.path) %>" class="list-group-item list-group-item-action">
<span class="category-post">More...</span>
</a>
<% break %>
<% } else { %>
<a href="<%- url_for(post.path) %>" class="list-group-item list-group-item-action">
<span class="category-post"><%= post.title %></span>
</a>
<% } %>
<% } %>
</div>
<% } %>
<div class="category-list">
<% cats = site.categories.find({parent: {$exists: false}}).sort(orderBy).filter(cat => cat.length) %>
<%- render_categories(cats) %>
</div>

View File

@ -1,27 +0,0 @@
<%
page.layout = "category"
page.title = [__('category.title'), page.category].join(" - ")
page.subtitle = [__('category.subtitle'), page.category].join(" - ")
page.banner_img = theme.category.banner_img
page.banner_img_height = theme.category.banner_img_height
page.banner_mask_alpha = theme.category.banner_mask_alpha
var cat = site.categories.find({name: page.category}).filter(cat => cat.length).data[0]
var date_cursor = 'xxx'
%>
<div class="list-group">
<p class="h4"><%= __('postTotal', cat ? cat.posts.length : 0) %></p>
<hr>
<% page.posts.each(function (post) { %>
<% if(date(post.date, "YYYY") != date_cursor) { %>
<% date_cursor = date(post.date, "YYYY") %>
<p class="h5"><%= date_cursor %></p>
<% } %>
<a href="<%- url_for(post.path) %>" class="list-group-item list-group-item-action">
<span class="archive-post-title"><%= post.title %></span>
<time style="float: right;"><%- date(post.date, "MM-DD") %></time>
</a>
<% }) %>
</div>
<%- partial('_partial/paginator') %>

View File

@ -1,70 +0,0 @@
<%
if (theme.index.slogan.enable) {
page.subtitle = theme.index.slogan.text || config.subtitle || ''
}
page.banner_img = theme.index.banner_img
page.banner_img_height = theme.index.banner_img_height
page.banner_mask_alpha = theme.index.banner_mask_alpha
%>
<% page.posts.each(function (post) { %>
<div class="row mx-auto index-card">
<% var post_url = url_for(post.path), index_img = post.index_img || theme.index.post_default_img %>
<% if(index_img) { %>
<div class="col-12 col-md-4 m-auto index-img">
<a href="<%- post_url %>" target="<%- theme.index.post_url_target %>">
<img src="<%- url_for(index_img) %>" alt="<%= post.title %>">
</a>
</div>
<% } %>
<article class="col-12 col-md-<%= index_img ? '8' : '12' %> mx-auto index-info">
<h1 class="index-header">
<% if (theme.index.post_sticky && theme.index.post_sticky.enable && post.sticky > 0) { %>
<i class="index-pin <%= theme.index.post_sticky && theme.index.post_sticky.icon %>" title="Pin on top"></i>
<% } %>
<a href="<%- post_url %>"><%= post.title %></a>
</h1>
<p class="index-excerpt">
<a href="<%- post_url %>">
<% var excerpt = '' %>
<% if(post.excerpt) { %>
<% excerpt = strip_html(post.excerpt).substr(0, 200) %>
<% } else if(theme.index.auto_excerpt.enable){ %>
<% excerpt = strip_html(post.content).substr(0, 200) %>
<% } %>
<%- excerpt %>
</a>
</p>
<div class="index-btm post-metas">
<% if(theme.index.post_meta.date ) { %>
<div class="post-meta mr-3">
<i class="iconfont icon-date"></i>
<time datetime="<%= full_date(post.date, 'YYYY-MM-DD HH:mm') %>" pubdate>
<%- date(post.date, config.date_format) %>
</time>
</div>
<% } %>
<% if(theme.index.post_meta.category && post.categories.length > 0) { %>
<div class="post-meta mr-3">
<i class="iconfont icon-category"></i>
<% post.categories.each(function(cate){ %>
<a href="<%= url_for(cate.path) %>"><%- cate.name %></a>
<% }) %>
</div>
<% } %>
<% if(theme.index.post_meta.tag && post.tags.length > 0) { %>
<div class="post-meta">
<i class="iconfont icon-tags"></i>
<% post.tags.each(function(tag){ %>
<a href="<%= url_for(tag.path) %>"><%- tag.name %></a>
<% }) %>
</div>
<% } %>
</div>
</article>
</div>
<% }) %>
<%- partial('_partial/paginator') %>

View File

@ -1,90 +0,0 @@
<%
var subtitle = page.subtitle || page.title
var banner_img = page.banner_img || theme.index.banner_img
var banner_img_height = page.banner_img_height || theme.index.banner_img_height
var banner_mask_alpha = page.banner_mask_alpha || theme.index.banner_mask_alpha
var colorSchema = theme.dark_mode && theme.dark_mode.enable && theme.dark_mode.default ? theme.dark_mode.default : ''
%>
<!DOCTYPE html>
<html lang="<%= config.language %>" <%= colorSchema ? `data-default-color-scheme="${colorSchema}"` : '' %>>
<%- partial('_partial/head') %>
<body>
<header style="height: <%- banner_img_height %>vh;">
<%- partial('_partial/nav') %>
<div class="banner intro-2" id="background" <%- theme.banner_parallax && 'parallax=true' %>
style="background: url('<%- url_for(banner_img) %>') no-repeat center center;
background-size: cover;">
<div class="full-bg-img">
<div class="mask flex-center" style="background-color: rgba(0, 0, 0, <%= parseFloat(banner_mask_alpha) %>)">
<div class="container page-header text-center fade-in-up">
<span class="h2" id="subtitle">
<% if(theme.fun_features.typing.enable == false) { %>
<%- subtitle %>
<% } %>
</span>
<% if(is_post() && page.meta !== false) { %>
<%- partial('_partial/post-meta') %>
<% } %>
</div>
<% if (theme.scroll_down_arrow.enable && theme.scroll_down_arrow.banner_height_limit <= banner_img_height && page.layout !== '404') { %>
<div class="scroll-down-bar">
<i class="iconfont icon-arrowdown"></i>
</div>
<% } %>
</div>
</div>
</div>
</header>
<main>
<% if(is_post() || page.layout === '404') { %>
<%- body %>
<% } else { %>
<div class="container nopadding-md">
<div class="py-5" id="board"
<%- banner_img_height >= 100 && theme.banner_parallax ? 'style=margin-top:0' : '' %>>
<% if(page.layout == 'about') { %>
<div class="about-avatar">
<img src="<%- url_for(theme.about.avatar) %>"
class="img-fluid" alt="avatar">
</div>
<% } %>
<div class="container">
<div class="row">
<div class="col-12 col-md-10 m-auto">
<%- body %>
</div>
</div>
</div>
</div>
</div>
<% } %>
</main>
<% if (theme.scroll_top_arrow.enable) { %>
<a id="scroll-top-button" href="#" role="button">
<i class="iconfont icon-arrowup" aria-hidden="true"></i>
</a>
<% } %>
<% if (theme.search.enable) { %>
<%- partial('_partial/search') %>
<% } %>
<% if (theme.custom_html) { %>
<div class="col-lg-7 mx-auto nopadding-md">
<div class="container custom mx-auto">
<%- theme.custom_html %>
</div>
</div>
<% } %>
<%- partial('_partial/footer', { data: { 'subtitle': subtitle } }) %>
</body>
</html>

View File

@ -1,29 +0,0 @@
<%
page.layout = "links"
page.title = theme.links.title || __('links.title')
page.subtitle = theme.links.subtitle || __('links.subtitle')
page.banner_img = theme.links.banner_img
page.banner_img_height = theme.links.banner_img_height
page.banner_mask_alpha = theme.links.banner_mask_alpha
%>
<div class="row links">
<% for(const each of theme.links.items || []) { %>
<% if (!each.title || !each.link) continue %>
<div class="card col-lg-4 col-md-6 col-sm-12">
<a href="<%= url_for(each.link) %>" class="card-body hover-with-bg" target="_blank" rel="noopener">
<div class="card-content">
<% if (each.image) { %>
<div class="link-avatar my-auto">
<img src="<%= each.image %>" alt="<%= each.title %>" />
</div>
<% } %>
<div class="link-text">
<div class="link-title"><%- each.title %></div>
<div class="link-intro"><%- each.intro %></div>
</div>
</div>
</a>
</div>
<% } %>
</div>

View File

@ -1,12 +0,0 @@
<%
var layout = page.layout
page.title = page.title || __(`${ layout }.title`)
page.subtitle = page.subtitle || page.title || __(`${ layout }.subtitle`)
page.banner_img = page.banner_img || theme.page.banner_img
page.banner_img_height = page.banner_img_height || theme.page.banner_img_height
page.banner_mask_alpha = page.banner_mask_alpha || theme.page.banner_mask_alpha
%>
<div class="page-content">
<%- page.content %>
</div>

View File

@ -1,105 +0,0 @@
<%
if (!page.banner_img) {
page.banner_img = theme.post.banner_img
}
page.banner_img_height = theme.post.banner_img_height
page.banner_mask_alpha = theme.post.banner_mask_alpha
%>
<div class="container-fluid">
<div class="row">
<div class="d-none d-lg-block col-lg-2"></div>
<div class="col-lg-8 nopadding-md">
<div class="container nopadding-md" id="board-ctn">
<div class="py-5" id="board">
<article class="post-content mx-auto" id="post">
<!-- SEO header -->
<h1 style="display: none"><%= page.subtitle || page.title %></h1>
<% if(theme.post.updated && theme.post.updated.enable) { %>
<p class="note note-info">
<% if (theme.post.updated.relative) { %>
<%- theme.post.updated.content %><%- relative_date(page.updated, theme.post.meta.date.format) %>
<% } else { %>
<%- theme.post.updated.content %><%- date(page.updated, theme.post.meta.date.format) %>
<% } %>
</p>
<% } %>
<div class="markdown-body" id="post-body">
<%- page.content %>
</div>
<hr>
<div>
<div class="post-metas mb-3">
<% if (page.categories && page.categories.length > 0) { %>
<div class="post-meta mr-3">
<i class="iconfont icon-category"></i>
<% page.categories.each(function(cate) { %>
<a class="hover-with-bg" href="<%= url_for(cate.path) %>"><%- cate.name %></a>
<% }) %>
</div>
<% } %>
<% if (page.tags && page.tags.length > 0 ) { %>
<div class="post-meta">
<i class="iconfont icon-tags"></i>
<% page.tags.each(function(tag) { %>
<a class="hover-with-bg" href="<%= url_for(tag.path) %>"><%- tag.name %></a>
<% }) %>
</div>
<% } %>
</div>
<% if(theme.post.copyright.enable && theme.post.copyright.content && page.copyright !== false) { %>
<p class="note note-warning"><%- theme.post.copyright.content %></p>
<% } %>
<% if(theme.post.prev_next.enable && !page.hide) { %>
<div class="post-prevnext row">
<article class="post-prev col-6">
<% const prev = prev_post(page) %>
<% if (prev) { %>
<a href="<%= url_for(prev.path) %>">
<i class="iconfont icon-arrowleft"></i>
<span class="hidden-mobile"><%- prev.title %></span>
<span class="visible-mobile"><%= __('post.pre') %></span>
</a>
<% } %>
</article>
<article class="post-next col-6">
<% const next = next_post(page) %>
<% if (next) { %>
<a href="<%= url_for(next.path) %>">
<span class="hidden-mobile"><%- next.title %></span>
<span class="visible-mobile"><%= __('post.next') %></span>
<i class="iconfont icon-arrowright"></i>
</a>
<% } %>
</article>
</div>
<% } %>
</div>
<% if(page.comments && theme.post.comments.enable) { %>
<!-- Comments -->
<article class="comments" id="comments">
<% var type = '_partial/comments/' + theme.post.comments.type %>
<%- partial(type) %>
</article>
<% } %>
</article>
</div>
</div>
</div>
<% if(theme.post.toc.enable && page.toc != false){ %>
<div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
<%- partial('_partial/toc') %>
</div>
<% } %>
</div>
</div>
<!-- Custom -->
<% if(theme.post.custom.enable && theme.post.custom.content && page.custom !== false) { %>
<div class="col-lg-7 mx-auto nopadding-md">
<div class="container custom post-content mx-auto">
<%- page.custom || theme.post.custom.content %>
</div>
</div>
<% } %>

View File

@ -1,27 +0,0 @@
<%
page.layout = "tag"
page.title = [__('tag.title'), page.tag].join(" - ")
page.subtitle = [__('tag.subtitle'), page.tag].join(" - ")
page.banner_img = theme.tag.banner_img
page.banner_img_height = theme.tag.banner_img_height
page.banner_mask_alpha = theme.tag.banner_mask_alpha
var tag = site.tags.find({name: page.tag}).filter(tag => tag.length).data[0]
var date_cursor = 'xxx'
%>
<div class="list-group">
<p class="h4"><%= __('postTotal', tag ? tag.posts.length : 0) %></p>
<hr>
<% page.posts.each(function (post) { %>
<% if(date(post.date, "YYYY") != date_cursor) { %>
<% date_cursor = date(post.date, "YYYY") %>
<p class="h5"><%= date_cursor %></p>
<% } %>
<a href="<%- url_for(post.path) %>" class="list-group-item list-group-item-action">
<span class="archive-post-title"><%= post.title %></span>
<time style="float: right;"><%- date(post.date, "MM-DD") %></time>
</a>
<% }) %>
</div>
<%- partial('_partial/paginator') %>

View File

@ -1,26 +0,0 @@
<%
page.layout = "tags"
page.title = theme.tag.title || __('tag.title')
page.subtitle = theme.tag.subtitle || __('tag.subtitle')
page.banner_img = theme.tag.banner_img
page.banner_img_height = theme.tag.banner_img_height
page.banner_mask_alpha = theme.tag.banner_mask_alpha
var min_font = theme.tag.tagcloud.min_font || 15
var max_font = theme.tag.tagcloud.max_font || 30
var unit = theme.tag.tagcloud.unit || 'px'
var start_color = theme.tag.tagcloud.start_color || '#BBBBEE'
var end_color = theme.tag.tagcloud.end_color || '#337ab7'
%>
<div class="text-center tagcloud">
<%- tagcloud({
min_font: min_font,
max_font: max_font,
amount: 999,
unit: unit,
color: true,
start_color,
end_color
}) %>
</div>

View File

@ -1,41 +0,0 @@
{
"name": "hexo-theme-fluid",
"version": "1.8.4",
"description": "An elegant Material-Design theme for Hexo.",
"main": "gulpfile.js",
"scripts": {
"lint": "gulp"
},
"repository": {
"type": "git",
"url": "git+https://github.com/fluid-dev/hexo-theme-fluid.git"
},
"keywords": [
"hexo",
"theme",
"fluid",
"material"
],
"author": "fluid-dev (https://github.com/fluid-dev)",
"license": "MIT",
"bugs": {
"url": "https://github.com/fluid-dev/hexo-theme-fluid/issues"
},
"homepage": "https://hexo.fluid-dev.com/docs",
"engines": {
"node": ">=10.13.0"
},
"devDependencies": {
"ejs-lint": "^1.1.0",
"gulp": "^4.0.2",
"gulp-eslint": "^6.0.0",
"gulp-shell": "^0.8.0",
"husky": "^4.3.0",
"js-yaml": "^3.14.0"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint"
}
}
}

View File

@ -1,16 +0,0 @@
/* global hexo */
'use strict';
hexo.on('generateBefore', () => {
require('./lib/hello')(hexo);
require('./lib/preset-configs')(hexo);
require('./lib/merge-configs')(hexo);
require('./lib/highlight')(hexo);
require('./lib/lazyload')(hexo);
require('./lib/footnote')(hexo);
});
hexo.on('generateAfter', () => {
require('./lib/version')(hexo);
});

View File

@ -1,100 +0,0 @@
'use strict';
// Register footnotes filter
module.exports = (hexo) => {
const config = hexo.theme.config;
if (config.post.footnote.enable) {
hexo.extend.filter.register('before_post_render', function(page) {
page.content = renderFootnotes(page.content, page.footnote);
return page;
});
}
/**
* Modify by https://github.com/kchen0x/hexo-reference
*
* Render markdown footnotes
* @param {String} text
* @param {String} header
* @returns {String} text
*/
function renderFootnotes(text, header) {
const reFootnoteContent = /\[\^(\d+)]: ?([\S\s]+?)(?=\[\^(?:\d+)]|\n\n|$)/g;
const reInlineFootnote = /\[\^(\d+)]\((.+?)\)/g;
const reFootnoteIndex = /\[\^(\d+)]/g;
let footnotes = [];
let html = '';
// threat all inline footnotes
text = text.replace(reInlineFootnote, function(match, index, content) {
footnotes.push({
index : index,
content: content
});
// remove content of inline footnote
return '[^' + index + ']';
});
// threat all footnote contents
text = text.replace(reFootnoteContent, function(match, index, content) {
footnotes.push({
index : index,
content: content
});
// remove footnote content
return '';
});
// create map for looking footnotes array
function createLookMap(field) {
let map = {};
for (let i = 0; i < footnotes.length; i++) {
const item = footnotes[i];
const key = item[field];
map[key] = item;
}
return map;
}
const indexMap = createLookMap('index');
// render (HTML) footnotes reference
text = text.replace(reFootnoteIndex,
function(match, index) {
if (!indexMap[index]) {
return match;
}
let tooltip = indexMap[index].content;
tooltip = hexo.render.renderSync({ text: tooltip, engine: 'markdown' });
tooltip = tooltip.replace(/(<.+?>)/g, '');
return '<sup id="fnref:' + index + '" class="footnote-ref">'
+ '<a href="#fn:' + index + '" rel="footnote">'
+ '<span class="hint--top hint--rounded" aria-label="'
+ tooltip
+ '">[' + index + ']</span></a></sup>';
});
// sort footnotes by their index
footnotes.sort(function(a, b) {
return a.index - b.index;
});
// render footnotes (HTML)
footnotes.forEach(function(footNote) {
html += '<li><span id="fn:' + footNote.index + '" class="footnote-text">';
html += '<span>';
const fn = hexo.render.renderSync({ text: footNote.content.trim(), engine: 'markdown' });
html += fn.replace(/(<p>)|(<\/p>)/g, '');
html += '<a href="#fnref:' + footNote.index + '" rev="footnote" class="footnote-backref"> ↩</a></span></span></li>';
});
// add footnotes at the end of the content
if (footnotes.length) {
text += '<section class="footnotes">';
text += header || config.post.footnote.header || '';
text += '<div class="footnote-list">';
text += '<ol>' + html + '</ol>';
text += '</div></section>';
}
return text;
}
};

View File

@ -1,19 +0,0 @@
'use strict';
module.exports = (hexo) => {
hexo.log.info(`
------------------------------------------------
| |
| ________ __ _ __ |
| |_ __ |[ | (_) | ] |
| | |_ \\_| | | __ _ __ .--.| | |
| | _| | |[ | | | [ |/ /'\`\\' | |
| _| |_ | | | \\_/ |, | || \\__/ | |
| |_____| [___]'.__.'_/[___]'.__.;__] |
| |
| Thank you for using Fluid theme ! |
| Docs: https://hexo.fluid-dev.com/docs/ |
| |
------------------------------------------------
`);
};

View File

@ -1,45 +0,0 @@
'use strict';
const objUtil = require('../../utils/object');
module.exports = (hexo) => {
const config = hexo.theme.config;
if (!config.code || !config.code.highlight.enable) {
return;
}
if (config.code.highlight.lib === 'highlightjs') {
// Force set hexo config
hexo.config.prismjs = objUtil.merge({}, hexo.config.prismjs, {
enable: false
});
hexo.config.highlight = objUtil.merge({}, hexo.config.highlight, {
enable : true,
hljs : true,
line_number: false,
wrap : false,
auto_detect: true
});
if (config.code.highlight.highlightjs.bg_color) {
hexo.extend.filter.register('after_render:html', (html, data) => {
return html.replace(/(?<!<div class="hljs">)<pre.*?(class=".+?".*?)*>(.*?)<\/pre>/gis, (str, p1, p2) => {
if (p2.search(/mermaid/) !== -1) {
return str;
}
return `<div class="hljs"><pre${p1 ? p1.replace('class="', ' class="hljs ') : ''}>${p2}</pre></div>`;
});
});
}
} else if (config.code.highlight.lib === 'prismjs') {
// Force set hexo config
hexo.config.highlight = objUtil.merge({}, hexo.config.highlight, {
enable: false
});
hexo.config.prismjs = objUtil.merge({}, hexo.config.prismjs, {
enable : true,
preprocess : config.code.highlight.prismjs.preprocess || false,
line_number: config.code.highlight.prismjs.line_number || false
});
}
};

View File

@ -1,33 +0,0 @@
'use strict';
const joinPath = require('../../utils/join-path');
module.exports = (hexo) => {
var config = hexo.theme.config;
let loadingImage = joinPath(joinPath(hexo.config.root, config.static_prefix.internal_img), 'loading.gif');
if (!config.lazyload || !config.lazyload.enable || !loadingImage) {
return;
}
if (config.lazyload.onlypost) {
hexo.extend.filter.register('after_post_render', function(page) {
if (page.source.search(/^_posts\/.+\.md$/) === -1 && !page.lazyload) {
return;
}
page.content = lazyProcess(page.content, loadingImage);
return page;
});
} else {
hexo.extend.filter.register('after_render:html', function(str, data) {
return lazyProcess(str, loadingImage);
});
}
};
const lazyProcess = (htmlContent, loadingImage) => {
return htmlContent.replace(/<img[^>]+src="(.*?)"[^>]*>/gi, (str, p1) => {
if (/srcset=/gi.test(str)) {
return str;
}
return str.replace(p1, `${p1}" srcset="${loadingImage}`);
});
};

View File

@ -1,52 +0,0 @@
'use strict';
const fs = require('fs');
const path = require('path');
const objUtil = require('../../utils/object');
module.exports = (hexo) => {
let dataConfig = {};
let dataStaticConfig = {};
if (hexo.locals.get) {
const data = hexo.locals.get('data');
if (data && data.fluid_config) {
dataConfig = data.fluid_config;
} else if (!configFromRoot(hexo)) {
const isZh = hexo.config.language.search(/zh-CN/i) !== -1;
if (isZh) {
hexo.log.warn('[Fluid] 推荐你使用覆盖配置功能: https://hexo.fluid-dev.com/docs/guide/#%E8%A6%86%E7%9B%96%E9%85%8D%E7%BD%AE');
} else {
hexo.log.warn('[Fluid] It is recommended that you use override configuration: https://hexo.fluid-dev.com/docs/en/guide/#override-configuration');
}
}
if (data && data.fluid_static_prefix) {
dataStaticConfig = data.fluid_static_prefix;
}
}
if (dataStaticConfig) {
hexo.theme.config.static_prefix = objUtil.merge({}, hexo.theme.config.static_prefix, dataStaticConfig);
hexo.log.debug('[Fluid] Merge data/fluid_static_prefix.yml into theme config.');
}
if (hexo.config.theme_config) {
hexo.theme.config = objUtil.merge({}, hexo.theme.config, hexo.config.theme_config);
hexo.log.debug('[Fluid] Merge theme_config in _config.yml into theme config.');
}
if (dataConfig) {
hexo.theme.config = objUtil.merge({}, hexo.theme.config, dataConfig);
hexo.log.debug('[Fluid] Merge data/fluid_config.yml into theme config.');
}
// Merge configs in hexo.config.theme_config into hexo.theme.config.
hexo.theme.config = objUtil.merge({}, hexo.theme.config, hexo.config.theme_config);
hexo.log.debug('[Fluid] Configs:\n', JSON.stringify(hexo.theme.config, undefined, 2));
};
const configFromRoot = (hexo) => {
const configPath = path.join(hexo.base_dir, '_config.fluid.yml');
return fs.existsSync(configPath);
};

View File

@ -1,40 +0,0 @@
'use strict';
module.exports = (hexo) => {
const isZh = hexo.config.language.search(/zh-CN/i) !== -1;
if (hexo.theme.config.highlight && !hexo.theme.config.code) {
if (isZh) {
hexo.log.warn('[Fluid] 检测到弃用的配置项: "highlight" 已被修改为 "code:highlight",请根据新版本更新');
} else {
hexo.log.warn('[Fluid] Deprecated config detected: "highlight" has been modified to "code:highlight", please update with the release.');
}
hexo.theme.config.code = {
copy_btn : hexo.theme.config.highlight.copy_btn,
highlight: {
enable : hexo.theme.config.highlight.enable,
lib : 'highlightjs',
highlightjs: {
style : hexo.theme.config.highlight.style,
bg_color: hexo.theme.config.highlight.bg_color
},
prismjs: {
style : 'default',
preprocess: true
}
}
};
}
// Some configs that require hexo >= 5.0
if (hexo.version[0] < '5') {
if (hexo.theme.config.code.highlight.lib === 'prismjs' && hexo.theme.config.code.highlight.prismjs.preprocess) {
hexo.theme.config.code.highlight.prismjs.preprocess = false;
if (isZh) {
hexo.log.warn('[Fluid] 检测到 Hexo 版本低于 5.0.0,配置项 "prismjs:preprocess" 参数值被强制设置为 false');
} else {
hexo.log.warn('[Fluid] Hexo version < 5.0.0 detected, "prismjs:preprocess" in theme config is forced to false.');
}
}
}
};

View File

@ -1,73 +0,0 @@
'use strict';
module.exports = (hexo) => {
if (!hexo.theme.config.version.check) {
return;
}
const https = require('https');
const path = require('path');
const { version } = require(path.normalize(path.join(hexo.theme_dir, 'package.json')));
const isZh = hexo.config.language.search(/zh-CN/i) !== -1;
const errorLog = (_) => {
if (isZh) {
hexo.log.warn('[Fluid] 获取主题最新版本信息失败,可能与 GitHub 连接不畅,不影响正常使用');
} else {
hexo.log.warn('[Fluid] Failed to detect version info. Don\'t worry, it won\'t hinder the use');
}
};
https.get('https://api.github.com/repos/fluid-dev/hexo-theme-fluid/releases/latest', {
headers: {
'User-Agent': 'Theme Fluid Client'
}
}, (res) => {
let result = '';
res.on('data', data => {
result += data;
});
res.on('end', () => {
try {
const tag = JSON.parse(result).tag_name;
if (!tag) {
errorLog('Missing release tag');
return;
}
const latest = tag.replace('v', '').split('.');
const current = version.split('.');
let isOutdated = false;
for (let i = 0; i < Math.max(latest.length, current.length); i++) {
if (!current[i] || latest[i] > current[i]) {
isOutdated = true;
break;
}
if (latest[i] < current[i]) {
break;
}
}
if (isOutdated) {
if (isZh) {
hexo.log.warn(`[Fluid] 你的主题版本已落后. 当前版本: v${current.join('.')}, 最新版本: v${latest.join('.')}`);
hexo.log.warn('[Fluid] 查看 https://github.com/fluid/hexo-theme-fluid/releases 获取更多信息.');
} else {
hexo.log.warn(`[Fluid] Your theme version is outdated. Current version: v${current.join('.')}, latest version: v${latest.join('.')}`);
hexo.log.warn('[Fluid] Visit https://github.com/fluid/hexo-theme-fluid/releases for more information.');
}
} else {
if (isZh) {
hexo.log.info(`[Fluid] 感谢支持!你现在使用的是最新版本,版本号: v${current.join('.')}`);
} else {
hexo.log.info(`[Fluid] Congratulations! Your are using the latest version of theme Fluid. Current version: v${current.join('.')}`);
}
}
} catch (err) {
errorLog(err);
}
});
}).on('error', err => {
errorLog(err);
});
};

View File

@ -1,27 +0,0 @@
/* global hexo */
'use strict';
// 生成前过滤文章
hexo.extend.filter.register('before_generate', function() {
this._bindLocals();
const all_posts = this.locals.get('posts');
const hide_posts = all_posts.filter(post => post.hide);
const normal_posts = all_posts.filter(post => !post.hide);
this.locals.set('all_posts', all_posts);
this.locals.set('hide_posts', hide_posts);
this.locals.set('posts', normal_posts);
});
const original_post_generator = hexo.extend.generator.get('post');
hexo.extend.generator.register('post', function(locals) {
// 发送时需要把过滤的页面也加入
return original_post_generator.bind(this)({
posts: new locals.posts.constructor(
locals.posts.data.concat(locals.hide_posts.data)
)
});
});

View File

@ -1,68 +0,0 @@
/* global hexo */
'use strict';
hexo.extend.generator.register('_hexo_generator_search', function(locals) {
const config = this.theme.config;
if (!config.search.enable) {
return;
}
const nunjucks = require('nunjucks');
const env = new nunjucks.Environment();
const pathFn = require('path');
const fs = require('fs');
env.addFilter('uriencode', function(str) {
return encodeURI(str);
});
env.addFilter('noControlChars', function(str) {
// eslint-disable-next-line no-control-regex
return str && str.replace(/[\x00-\x1F\x7F]/g, '');
});
env.addFilter('urlJoin', function(str) {
const base = str[0];
const relative = str[1];
return relative
? base.replace(/\/+$/, '') + '/' + relative.replace(/^\/+/, '')
: base;
});
const searchTmplSrc = pathFn.join(hexo.theme_dir, './source/xml/local-search.xml');
const searchTmpl = nunjucks.compile(fs.readFileSync(searchTmplSrc, 'utf8'), env);
const searchConfig = config.search;
let searchField = searchConfig.field;
const content = searchConfig.content || true;
let posts, pages;
if (searchField.trim() !== '') {
searchField = searchField.trim();
if (searchField === 'post') {
posts = locals.posts.sort('-date');
} else if (searchField === 'page') {
pages = locals.pages;
} else {
posts = locals.posts.sort('-date');
pages = locals.pages;
}
} else {
posts = locals.posts.sort('-date');
}
const xml = searchTmpl.render({
config : config,
posts : posts,
pages : pages,
content: content,
url : hexo.config.root
});
return {
path: searchConfig.generate_path || '/local-search.xml',
data: xml
};
});

View File

@ -1,44 +0,0 @@
/* global hexo */
'use strict';
const fs = require('fs');
const path = require('path');
// generate 404 page
if (!fs.existsSync(path.join(hexo.source_dir, '404.html'))) {
hexo.extend.generator.register('_404', function(locals) {
return {
path : '404.html',
data : locals.theme,
layout: '404'
};
});
}
// generate tags Page
hexo.extend.generator.register('_tags', function(locals) {
return {
path : 'tags/index.html',
data : locals.theme,
layout: 'tags'
};
});
// generate categories Page
hexo.extend.generator.register('_categories', function(locals) {
return {
path : 'categories/index.html',
data : locals.theme,
layout: 'categories'
};
});
// generate links page
hexo.extend.generator.register('_links', function(locals) {
return {
path : 'links/index.html',
data : locals.theme,
layout: 'links'
};
});

View File

@ -1,25 +0,0 @@
/* global hexo */
'use strict';
hexo.extend.helper.register('prev_post', function prev_post(post) {
const prev = post.prev;
if (!prev) {
return null;
}
if (prev.hide) {
return prev_post(prev);
}
return prev;
});
hexo.extend.helper.register('next_post', function next_post(post) {
const next = post.next;
if (!next) {
return null;
}
if (next.hide) {
return next_post(next);
}
return next;
});

View File

@ -1,17 +0,0 @@
/* global hexo */
'use strict';
const joinPath = require('../utils/join-path');
hexo.extend.helper.register('css_ex', function(base, relative, ex = '') {
return `<link ${ex} rel="stylesheet" href="${this.url_for(joinPath(base, relative))}" />`;
});
hexo.extend.helper.register('js_ex', function(base, relative, ex = '') {
return `<script ${ex} src="${this.url_for(joinPath(base, relative))}" ></script>`;
});
hexo.extend.helper.register('url_join', function(base, relative) {
return this.url_for(joinPath(base, relative));
});

View File

@ -1,9 +0,0 @@
/* global hexo */
'use strict';
const crypto = require('crypto');
hexo.extend.helper.register('md5', function(string) {
return crypto.createHash('md5').update(string).digest('hex');
});

View File

@ -1,38 +0,0 @@
/* global hexo */
'use strict';
let counter = function(content) {
content = require('hexo-util').stripHTML(content);
const cn = (content.match(/[\u4E00-\u9FA5]/g) || []).length;
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;
return [cn, en];
};
hexo.extend.helper.register('min2read', function(content, { cn = 300, en = 160 } = {}) {
let len = counter(content);
let readingTime = (len[0] / cn) + (len[1] / en);
return readingTime < 1 ? '1' : parseInt(readingTime, 10);
});
hexo.extend.helper.register('wordcount', function(content) {
let len = counter(content);
let count = len[0] + len[1];
if (count < 1000) {
return count;
}
return (Math.round(count / 100) / 10) + 'k';
});
hexo.extend.helper.register('totalcount', function(site) {
let count = 0;
site.posts.forEach(function(post) {
let len = counter(post.content);
count += len[0] + len[1];
});
if (count < 1000) {
return count;
}
return (Math.round(count / 100) / 10) + 'k';
});

View File

@ -1,18 +0,0 @@
/* global hexo */
'use strict';
const button = (args) => {
args = args.join(' ').split(',');
const url = (args[0] || '').trim();
const text = (args[1] || '').trim();
const title = (args[2] || '').trim();
!url && hexo.log.warn('[Fluid] Button url must be defined!');
return `<a class="btn" href="${url}" ${title.length > 0 ? ` title="${title}"` : ''} target="_blank">${text}</a>`;
};
// {% btn url, text, title %}
hexo.extend.tag.register('button', button, { ends: false });
hexo.extend.tag.register('btn', button, { ends: false });

View File

@ -1,27 +0,0 @@
/* global hexo */
'use strict';
const checkbox = (args) => {
args = args[0] === ',' ? args.slice(1) : args;
args = args.join(' ').split(',');
const text = (args[0] || '').trim();
if (text === 'checked' || text === 'true' || text === 'false') {
const checked = text === 'checked' || text === 'true';
return `<input type="checkbox" disabled ${checked ? 'checked="checked"' : ''}>`;
}
!text && hexo.log.warn('[Fluid] Checkbox text must be defined!');
const checked = (args[1] || '').length > 0 && args[1].trim() !== 'false';
const inline = (args[2] || '').length > 0 && args[2].trim() !== 'false';
return `${!inline ? '<div>' : ''}
<input type="checkbox" disabled ${checked ? 'checked="checked"' : ''}>${text}
${!inline ? '</div>' : ''}`;
};
// {% cb text, checked?, inline? %}
hexo.extend.tag.register('checkbox', checkbox, { ends: false });
hexo.extend.tag.register('cb', checkbox, { ends: false });

View File

@ -1,78 +0,0 @@
/* global hexo */
'use strict';
const DEFAULT_LAYOUTS = {
2 : [1, 1],
3 : [2, 1],
4 : [2, 2],
5 : [3, 2],
6 : [3, 3],
7 : [3, 2, 2],
8 : [3, 2, 3],
9 : [3, 3, 3],
10: [3, 2, 2, 3]
};
const groupBy = (total, layout) => {
const r = [];
for (let count of total) {
r.push(layout.slice(0, count));
layout = layout.slice(count);
}
return r;
};
const templates = {
dispatch: (images, total, layout) => {
const valid = layout && (layout.reduce((prev, current) => prev + current) === total);
const _layout = valid ? layout : DEFAULT_LAYOUTS[total];
return _layout ? templates.getHTML(groupBy(_layout, images)) : templates.defaults(images);
},
defaults: (images) => {
const ROW_SIZE = 3;
const rows = images.length / ROW_SIZE;
const imageArr = [];
for (let i = 0; i < rows; i++) {
imageArr.push(images.slice(i * ROW_SIZE, (i + 1) * ROW_SIZE));
}
return templates.getHTML(imageArr);
},
getHTML: (rows) => {
return rows.map(row => {
return `<div class="group-image-row">${templates.getColumnHTML(row)}</div>`;
}).join('');
},
getColumnHTML: (images) => {
return images.map(image => {
return `<div class="group-image-wrap">${image}</div>`;
}).join('');
}
};
const groupImage = (args, content) => {
const total = parseInt(args[0], 10);
const layout = args[1] && args[1].split('-').map((v) => parseInt(v, 10));
content = hexo.render.renderSync({ text: content, engine: 'markdown' });
const images = content.match(/<img[\s\S]*?>/g);
return `<div class="group-image-container">${templates.dispatch(images, total, layout)}</div>`;
};
/*
{% groupimage total n1-n2-n3-... %}
![](url)
![](url)
![](url)
{% endgroupimage %}
*/
hexo.extend.tag.register('groupimage', groupImage, { ends: true });
hexo.extend.tag.register('gi', groupImage, { ends: true });

View File

@ -1,16 +0,0 @@
/* global hexo */
'use strict';
const label = (args) => {
args = args.join(' ').split('@');
const classes = args[0] || 'default';
const text = args[1] || '';
!text && hexo.log.warn('[Fluid] Label text must be defined!');
return `<span class="label label-${classes.trim()}">${text}</span>`;
};
// {% label class @text %}
hexo.extend.tag.register('label', label, { ends: false });

View File

@ -1,19 +0,0 @@
/* global hexo */
'use strict';
const note = (args, content) => {
if (!args || !args[0]) {
args = ['primary'];
}
return `<div class="note note-${args.join(' ')}">
${hexo.render.renderSync({ text: content, engine: 'markdown' }).split('\n').join('')}
</div>`;
};
/*
{% note class %}
text
{% endnote %}
*/
hexo.extend.tag.register('note', note, { ends: true });

View File

@ -1,12 +0,0 @@
'use strict';
const joinPath = function(base, relative) {
if (relative && /^https*:\/\//.test(relative)) {
return relative;
}
return relative
? base.replace(/\/+$/, '') + '/' + relative.replace(/^\/+/, '')
: base;
};
module.exports = joinPath;

View File

@ -1,26 +0,0 @@
'use strict';
const isObject = (item) => {
return item && typeof item === 'object' && !Array.isArray(item);
};
const merge = (target, ...sources) => {
for (const source of sources) {
for (const key in source) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
continue;
}
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
};
module.exports = {
isObject: isObject,
merge : merge
};

View File

@ -1,8 +0,0 @@
theme-config(config, predef)
unquote(hexo-config(config) ? hexo-config(config):predef)
theme-config-unit(config, predef, unit)
unit(hexo-config(config) ? hexo-config(config):predef, unit)
theme-config-origin(config, predef)
(hexo-config(config) ? hexo-config(config):predef)

View File

@ -1,23 +0,0 @@
/* */
anchor-offset()
&::before
display block
content ""
margin-top -5rem
height 5rem
width 1px
visibility hidden
/* */
ground-glass($px, $bg-color, $alpha)
/* backdrop-filter */
@supports (-webkit-backdrop-filter: blur($px)) or (backdrop-filter: blur($px))
&
background rgba(convert($bg-color), $alpha)
-webkit-backdrop-filter blur($px)
backdrop-filter blur($px)
/* 使 */
@supports not ((-webkit-backdrop-filter: blur($px)) or (backdrop-filter: blur($px)))
&
background rgb(convert($bg-color))

View File

@ -1,34 +0,0 @@
.about-avatar
position relative
margin -8rem auto 1rem
width 10rem
height 10rem
z-index 3
img
width 100%
height 100%
border-radius 50%
-moz-border-radius 50%
-webkit-border-radius 50%
object-fit cover
-webkit-box-shadow 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12)
box-shadow 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12)
.about-info
& > div
margin-bottom .5rem
.about-name
font-size 1.75rem
font-weight bold
.about-intro
font-size 1rem
.about-icons
& > a:not(:last-child)
margin-right .5rem
& > a > i
font-size 1.5rem

View File

@ -1,3 +0,0 @@
.list-group
a ~ p.h5
margin-top 1rem

View File

@ -1,20 +0,0 @@
.banner
height 100%
position relative
overflow hidden
cursor default
overflow-wrap break-word
.mask
position absolute
width 100%
height 100%
background-color rgba(0, 0, 0, 0.3)
.page-header
color #fff
&[parallax="true"]
will-change transform
-webkit-transform-style preserve-3d
-webkit-backface-visibility hidden

View File

@ -1,9 +0,0 @@
#board
position relative
margin-top -2rem
background-color var(--board-bg-color)
transition background-color .2s ease-in-out
border-radius 0.5rem
z-index 3
-webkit-box-shadow 0 12px 15px 0 rgba(0, 0, 0, 0.24), 0 17px 50px 0 rgba(0, 0, 0, 0.19)
box-shadow 0 12px 15px 0 rgba(0, 0, 0, 0.24), 0 17px 50px 0 rgba(0, 0, 0, 0.19)

View File

@ -1,42 +0,0 @@
.copy-btn
display inline-block
cursor pointer
border-radius .1rem
border none
background-color transparent
-webkit-user-select none
-moz-user-select none
-ms-user-select none
user-select none
-webkit-appearance none
font-size .75rem
line-height 1
font-weight bold
outline none
-webkit-transition opacity .2s ease-in-out
-o-transition opacity .2s ease-in-out
transition opacity .2s ease-in-out
padding .25rem
position absolute
right .5rem
top .25rem
opacity 0
& > i
font-size .75rem
font-weight 400
& > span
margin-left 5px
.copy-btn-dark
color #6a737d
.copy-btn-light
color #bababa
.markdown-body pre:hover > .copy-btn
opacity 0.9
.markdown-body pre:hover > .copy-btn, .markdown-body pre:not(:hover) > .copy-btn
outline none

View File

@ -1,23 +0,0 @@
footer > div:not(:first-child)
margin .25rem 0
font-size .85rem
.statistics > span:last-child
margin 0 .35rem
a.beian-police
position relative
overflow hidden
display inline-flex
align-items center
justify-content center
img
margin 0 3px
width 18px
height 18px
@media (max-width: 320px)
a.beian-police
span.beian-police-sep
display none

View File

@ -1,25 +0,0 @@
sup > a, .footnote-text
anchor-offset()
&::before
display inline-block
.footnote-item
anchor-offset()
.footnote-list
ol
list-style-type none
counter-reset sectioncounter
padding-left .5rem
font-size .95rem
li:before
font-family "Helvetica Neue", monospace, "Monaco"
content "["counter(sectioncounter)"]"
counter-increment sectioncounter
li+li
margin-top .5rem
.footnote-text
padding-left .5em

View File

@ -1,4 +0,0 @@
@media (max-width: 767px)
header
.h2
font-size 1.5rem

Some files were not shown because too many files have changed in this diff Show More