hexo-theme-shokax 0.2.3 → 0.2.5-beta1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  ![LICENSE]( https://img.shields.io/github/license/theme-shoka-x/hexo-theme-shokaX)
6
6
  ![stars](https://img.shields.io/github/stars/theme-shoka-x/hexo-theme-shokaX)
7
7
  ![version](https://shields.io/npm/v/hexo-theme-shokax)
8
+ ![build](https://img.shields.io/github/actions/workflow/status/theme-shoka-x/hexo-theme-shokaX/build-theme.yml)
8
9
 
9
10
  语言(language): 简体中文 | [English](./README_en.md) \
10
11
  此项目是shoka的一个二次开发版(算精神续作),致力于提高性能和优化魔改体验 \
@@ -24,15 +25,17 @@ shokaX的社区资源导航和插件仓库为[awesome-shokaX](https://github.com
24
25
  | PWA支持 | ✅ | JSD拆分 | ✅ |
25
26
  | 注入API | ✅ | 社区插件系统 | ✅ |
26
27
  | 自定义字体 | ✅* | 自定义样式 | ✅* |
27
- | 多种评论系统支持 | ✅ | 用户行为分析支持 | |
28
+ | 多种评论系统支持 | ✅ | AI生成文章概括 | 🔬 |
28
29
  | 底部备案号 | ✅ | 自定义页尾 | ✅* |
29
30
  | CSS渐变封面 | ✅ | typescript支持 | ✅ |
30
31
 
31
32
  备注:
32
33
  - *: 需要使用注入API实现
34
+ - 🔬: 实验中,可能存在问题
33
35
 
34
36
 
35
37
  ## 🔧 如何安装?
38
+ 注意: 本项目需要 node.js 18.x 或更高版本才能运行 \
36
39
  建议使用[ShokaX-CLI](https://github.com/zkz098/shokaX-CLI) ,执行下列命令即可:
37
40
  ```bash
38
41
  npm i shokax-cli --location=global
@@ -57,7 +60,7 @@ github仓库建议通过右边的 releases 下载,步骤为:
57
60
  - [Easy hexo](https://easyhexo.com/)
58
61
 
59
62
  # 许可证
60
- 许可证: GPL 3 \
63
+ 许可证: GPL 3 or later \
61
64
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fzkz098%2Fhexo-theme-shokaX.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fzkz098%2Fhexo-theme-shokaX?ref=badge_large)
62
65
 
63
66
  ## 特别说明
@@ -76,3 +79,6 @@ GPL许可证主要目的是限制修改后的分发行为,避免未经许可
76
79
 
77
80
  ## 特别鸣谢
78
81
  [<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" width="25%">](https://jb.gg/OpenSourceSupport)
82
+
83
+ ## 其他信息
84
+ ![Star history chart](https://api.star-history.com/svg?repos=theme-shoka-x/hexo-theme-shokaX&type=Date)
package/README_en.MD CHANGED
@@ -1,25 +1,56 @@
1
+ If the repository address you are visiting is zkz098/hexo-theme-shokaX, please switch to the latest address: theme-shoka-x/hexo-theme-shokaX.
2
+
1
3
  # hexo-theme-shokaX
2
4
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fzkz098%2Fhexo-theme-shokaX.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fzkz098%2Fhexo-theme-shokaX?ref=badge_shield)
3
- ![LICENSE]( https://img.shields.io/github/license/zkz098/hexo-theme-shokaX)
4
- ![stars](https://img.shields.io/github/stars/zkz098/hexo-theme-shokaX)
5
+ ![LICENSE]( https://img.shields.io/github/license/theme-shoka-x/hexo-theme-shokaX)
6
+ ![stars](https://img.shields.io/github/stars/theme-shoka-x/hexo-theme-shokaX)
5
7
  ![version](https://shields.io/npm/v/hexo-theme-shokax)
8
+ ![build](https://img.shields.io/github/actions/workflow/status/theme-shoka-x/hexo-theme-shokaX/build-theme.yml)
9
+
10
+ Language: [简体中文](./README.md) | English \
11
+ This project is a secondary development version of shoka (spiritual sequel), dedicated to improving performance and optimizing modding experience.
12
+ The reason for its birth is that shoka has not been updated for two years, with a large backlog of bugs and feature requests.
13
+
14
+ The community resource navigation and plugin repository for shokaX is awesome-shokaX.
15
+
16
+ ## 💬 Differences with shoka
17
+ The original shoka used javascript+Native+nunjucks technology, while shokaX uses typescript+Vue 3+Pug technology and has changed a lot of hard-to-access CDN links.
18
+
19
+ ## ✨ Feature List
20
+ | Feature Name | Implementation Status | Feature Name | Implementation Status |
21
+ |:-------------------------------:|:---------------------:|:------------------------------:|:---------------------:|
22
+ | PWA Support | ✅ | JSD Splitting | ✅ |
23
+ | Injection API | ✅ | Community Plugin System | ✅ |
24
+ | Custom Fonts | ✅* | Custom Styles | ✅* |
25
+ | Multiple Comment System Support | ✅ | User Behavior Analysis Support | ✅ |
26
+ | Record Number at the Bottom | ✅ | Custom Footer | ✅* |
27
+ | CSS Gradient Cover | ✅ | Typescript Support | ✅ |
6
28
 
7
- 语言(language): [简体中文](./README.md) | English \
8
- This project is a secondary development version of Shoka, dedicated to improving performance and optimizing the development experience. \
9
- This project is in a period of intensive development, but the github repository version is basically available. \
10
- Please refer to the wiki for secondary development and common problems.
11
- Starting with `0.0.2-alpha2`, `lantern` and `qweather` have been migrated as plugins.
12
- The plugin system is complete, see [awesome-shokaX](https://github.com/zkz098/awesome-shokaX) for how to use it.
29
+ Remarks:
30
+ - *: Requires implementation using Injection API.
13
31
 
14
- ## How to install?
15
- [ShokaX-CLI](https://github.com/zkz098/shokaX-CLI) is recommended:
32
+ ## 🔧 How to Install?
33
+ It is recommended to use [ShokaX-CLI](https://github.com/zkz098/shokaX-CLI) and execute the following command:
16
34
  ```bash
17
35
  npm i shokax-cli --location=global
18
- # hexo init
19
- SXC install -r=github shokaX
36
+ # hexo init initializes the environment
37
+ SXC install shokaX
20
38
  ```
39
+ [Click here](https://docs.kaitaku.xyz/guide/#%E9%85%8D%E7%BD%AE%E4%B8%BB%E9%A2%98) for the next configuration steps.
40
+
41
+ It is recommended to download the GitHub repository from the Releases on the right-hand side, as follows:
42
+
43
+ - Click on the Latest version in Releases
44
+ - Download the Source code(zip) in Assets
45
+ - Unzip to use as the theme
21
46
 
22
47
  # License
23
- License: BSD-3-Clause \
48
+ license: GPL 3 or later
24
49
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fzkz098%2Fhexo-theme-shokaX.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fzkz098%2Fhexo-theme-shokaX?ref=badge_large)
25
50
 
51
+ ## Contributors
52
+
53
+ [![](https://contributors-img.web.app/image?repo=zkz098/hexo-theme-shokaX)](https://github.com/zkz098/hexo-theme-shokaX/graphs/contributors)
54
+
55
+ ## Special thanks
56
+ [<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" width="25%">](https://jb.gg/OpenSourceSupport)
package/_config.yml CHANGED
@@ -198,6 +198,17 @@ giscus:
198
198
  commentTheme:
199
199
  lang:
200
200
 
201
+ summary:
202
+ enable: false
203
+ introduce: "我是基于ChatGPT-turbo-3.5实现的AI助手,在此网站上负责整理和概括文章" # AI自我介绍
204
+ mode: openai # openai/custom
205
+ openai:
206
+ remote: "https://api.openai.com"
207
+ apikey: "key"
208
+ custom:
209
+ remote: "http://localhost:8000"
210
+
211
+
201
212
  # Social Links
202
213
  # Usage: `Key: permalink || icon || color`
203
214
  # Key is the link label showing to end users.
@@ -344,7 +355,7 @@ advVendors:
344
355
  fetch:
345
356
  src: npm:whatwg-fetch@3.4.0/dist/fetch.umd.js
346
357
  anime:
347
- src: bytedance:animejs/3.2.0/anime.min.js
358
+ src: npm:theme-shokax-anime@latest/anime.shokax.min.js
348
359
  algolia:
349
360
  src: bytedance:algoliasearch/4.12.1/algoliasearch-lite.umd.min.js
350
361
  instantsearch:
@@ -394,7 +405,7 @@ vendors:
394
405
  pace: npm/pace-js@1.0.2/pace.min.js # ok
395
406
  pjax: npm/pjax@0.2.8/pjax.min.js # ok
396
407
  fetch: npm/whatwg-fetch@3.4.0/dist/fetch.umd.min.js # ok
397
- anime: npm/animejs@3.2.0/lib/anime.min.js # ok
408
+ anime: npm/theme-shokax-anime@latest/anime.shokax.min.js
398
409
  algolia: npm/algoliasearch@4/dist/algoliasearch-lite.umd.js # ok
399
410
  instantsearch: npm/instantsearch.js@4/dist/instantsearch.production.min.js # ok
400
411
  lazyload: npm/lozad@1/dist/lozad.min.js # ok
@@ -1,6 +1,5 @@
1
1
  mixin PMRender(item, full)
2
2
  - full ||= false
3
- //- 下方的_content为暴力修复法,在未来需要重写
4
3
  div(class="meta")
5
4
  - var create_title = __('post.created') + __('symbol.colon') + full_date(item.date)
6
5
  span(class="item" title=create_title)
@@ -12,6 +12,19 @@ article(itemscope itemtype="http://schema.org/Article" class="post block" lang=t
12
12
  div(class="gallery" itemscope itemtype="http://schema.org/ImageGallery")
13
13
  each photo in post.photos
14
14
  img(data-src=_image_url(photo, post.path) itemprop="contentUrl")
15
+ if theme.summary.enable && page.layout === 'post'
16
+ div(class='tabs' id='summary')
17
+ div(class="show-btn")
18
+ div(class="nav")
19
+ ul(class="special")
20
+ div(class="tab" data-id="summary" data-title="自我介绍")
21
+ p
22
+ != get_introduce()
23
+ div(class="tab active" data-id="summary" data-title="文章概括")
24
+ p
25
+ != get_summary(page)
26
+
27
+
15
28
  != post.content
16
29
  if post.tags && post.tags.length
17
30
  div(class="tags")
package/package.json CHANGED
@@ -1,49 +1,48 @@
1
1
  {
2
2
  "name": "hexo-theme-shokax",
3
- "version": "0.2.3",
3
+ "version": "0.2.5-beta1",
4
4
  "description": "a hexo theme based on shoka",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/zkz098/hexo-theme-shokaX",
7
7
  "author": "Chou kaitaku",
8
8
  "license": "GPL-3.0-or-later",
9
9
  "scripts": {
10
- "test": "cd ./source/js && tsc",
10
+ "test": "tsc",
11
11
  "build": "pnpm install && tsc",
12
12
  "docs:dev": "vuepress dev docs",
13
13
  "docs:build": "vuepress build docs"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@algolia/client-search": "^4",
17
- "@types/animejs": "^3.1.7",
18
17
  "@types/fancybox": "^3.5.3",
19
18
  "@types/hexo": "^3.8.8",
20
19
  "@types/jquery": "^3.5.16",
21
20
  "@types/js-yaml": "^4.0.5",
22
21
  "@types/lozad": "^1.16.1",
23
- "@types/node": "^18.15.6",
24
- "@types/shelljs": "^0.8.11",
25
- "@typescript-eslint/eslint-plugin": "^5.56.0",
26
- "@typescript-eslint/parser": "^5.56.0",
22
+ "@types/node": "^18.15.13",
23
+ "@typescript-eslint/eslint-plugin": "^5.59.0",
24
+ "@typescript-eslint/parser": "^5.59.0",
27
25
  "@vuepress/client": "2.0.0-beta.61",
28
26
  "@vuepress/plugin-docsearch": "2.0.0-beta.61",
29
- "algoliasearch": "^4.16.0",
30
- "eslint": "^8.36.0",
27
+ "algoliasearch": "^4.17.0",
28
+ "eslint": "^8.39.0",
31
29
  "eslint-config-standard": "^17.0.0",
32
30
  "eslint-plugin-import": "^2.27.5",
33
- "eslint-plugin-n": "^15.6.1",
31
+ "eslint-plugin-n": "^15.7.0",
34
32
  "eslint-plugin-promise": "^6.1.1",
35
- "eslint-plugin-vue": "^9.10.0",
33
+ "eslint-plugin-vue": "^9.11.0",
36
34
  "hexo-fs": "^4.1.1",
37
35
  "hexo-util": "^3.0.1",
38
- "instantsearch.js": "^4.53.0",
36
+ "instantsearch.js": "^4.54.1",
39
37
  "pjax": "^0.2.8",
40
- "typescript": "^5.0.2",
38
+ "theme-shokax-anime": "^0.0.4",
39
+ "typescript": "^5.0.4",
41
40
  "vue": "^3.2.47",
42
41
  "vuepress": "2.0.0-beta.61",
43
- "vuepress-plugin-sitemap2": "2.0.0-beta.197"
42
+ "vuepress-plugin-sitemap2": "2.0.0-beta.206"
44
43
  },
45
44
  "dependencies": {
46
45
  "js-yaml": "^4.1.0",
47
- "sass": "^1.60.0"
46
+ "sass": "^1.62.0"
48
47
  }
49
48
  }
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const hexo_util_1 = __importDefault(require("hexo-util"));
7
- const hexo_fs_1 = __importDefault(require("hexo-fs"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const js_yaml_1 = __importDefault(require("js-yaml"));
10
10
  hexo.extend.filter.register('before_generate', () => {
@@ -26,7 +26,7 @@ hexo.extend.filter.register('before_generate', () => {
26
26
  hexo.theme.config.style = {};
27
27
  for (const style of ['iconfont', 'colors', 'custom']) {
28
28
  const custom_file = 'source/_data/' + style + '.styl';
29
- if (hexo_fs_1.default.existsSync(custom_file)) {
29
+ if (node_fs_1.default.existsSync(custom_file)) {
30
30
  hexo.theme.config.style[style] = path_1.default.resolve(hexo.base_dir, custom_file);
31
31
  }
32
32
  }
@@ -34,6 +34,6 @@ hexo.extend.filter.register('before_generate', () => {
34
34
  hexo.theme.config.image_list = data.images;
35
35
  }
36
36
  else {
37
- hexo.theme.config.image_list = js_yaml_1.default.load(hexo_fs_1.default.readFileSync(path_1.default.join(__dirname, '../../_images.yml')));
37
+ hexo.theme.config.image_list = js_yaml_1.default.load(node_fs_1.default.readFileSync(path_1.default.join(__dirname, '../../_images.yml')));
38
38
  }
39
39
  });
@@ -1,22 +1,19 @@
1
1
  'use strict';
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const hexo_fs_1 = __importDefault(require("hexo-fs"));
3
+ const fs = require("hexo-fs");
7
4
  hexo.extend.generator.register('images', function (locals) {
8
5
  const theme = hexo.theme.config;
9
6
  const dir = 'source/_data/' + theme.assets + '/';
10
- if (!hexo_fs_1.default.existsSync(dir)) {
7
+ if (!fs.existsSync(dir)) {
11
8
  return;
12
9
  }
13
10
  const result = [];
14
- const files = hexo_fs_1.default.listDirSync(dir);
11
+ const files = fs.listDirSync(dir);
15
12
  files.forEach((file) => {
16
13
  result.push({
17
14
  path: theme.assets + '/' + file,
18
15
  data: function () {
19
- return hexo_fs_1.default.createReadStream(dir + file);
16
+ return fs.createReadStream(dir + file);
20
17
  }
21
18
  });
22
19
  });
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const hexo_fs_1 = __importDefault(require("hexo-fs"));
6
+ const fs = require("hexo-fs");
7
7
  const hexo_pagination_1 = __importDefault(require("hexo-pagination"));
8
8
  hexo.config.index_generator = Object.assign({
9
9
  per_page: typeof hexo.config.per_page === 'undefined' ? 10 : hexo.config.per_page,
@@ -31,27 +31,27 @@ hexo.extend.generator.register('index', function (locals) {
31
31
  if (categories && categories.length) {
32
32
  categories.forEach((cat) => {
33
33
  const cover = `source/_posts/${cat.slug}`;
34
- if (hexo_fs_1.default.existsSync(cover + '/cover.avif')) {
34
+ if (fs.existsSync(cover + '/cover.avif')) {
35
35
  covers.push({
36
36
  path: cat.slug + '/cover.avif',
37
37
  data: function () {
38
- return hexo_fs_1.default.createReadStream(cover + '/cover.avif');
38
+ return fs.createReadStream(cover + '/cover.avif');
39
39
  }
40
40
  });
41
41
  }
42
- else if (hexo_fs_1.default.existsSync(cover + '/cover.webp')) {
42
+ else if (fs.existsSync(cover + '/cover.webp')) {
43
43
  covers.push({
44
44
  path: cat.slug + '/cover.webp',
45
45
  data: function () {
46
- return hexo_fs_1.default.createReadStream(cover + '/cover.webp');
46
+ return fs.createReadStream(cover + '/cover.webp');
47
47
  }
48
48
  });
49
49
  }
50
- else if (hexo_fs_1.default.existsSync(cover + '/cover.jpg')) {
50
+ else if (fs.existsSync(cover + '/cover.jpg')) {
51
51
  covers.push({
52
52
  path: cat.slug + '/cover.jpg',
53
53
  data: function () {
54
- return hexo_fs_1.default.createReadStream(cover + '/cover.jpg');
54
+ return fs.createReadStream(cover + '/cover.jpg');
55
55
  }
56
56
  });
57
57
  const topcat = getTopcat(cat);
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const package_json_1 = __importDefault(require("../../package.json"));
7
- const hexo_fs_1 = __importDefault(require("hexo-fs"));
7
+ const fs = require("hexo-fs");
8
8
  hexo.extend.generator.register('script', function (locals) {
9
9
  const log = hexo.log || console.log;
10
10
  const config = hexo.config;
@@ -61,27 +61,27 @@ hexo.extend.generator.register('script', function (locals) {
61
61
  }
62
62
  let text = '';
63
63
  ['library', 'global', 'page', 'vue', 'components'].forEach(function (item) {
64
- if (hexo_fs_1.default.existsSync(`themes/shokaX/source/js/_app/${item}.js`)) {
65
- text += hexo_fs_1.default.readFileSync(`themes/shokaX/source/js/_app/${item}.js`).toString();
64
+ if (fs.existsSync(`themes/shokaX/source/js/_app/${item}.js`)) {
65
+ text += fs.readFileSync(`themes/shokaX/source/js/_app/${item}.js`).toString();
66
66
  }
67
67
  else {
68
- text += hexo_fs_1.default.readFileSync(`node_modules/hexo-theme-shokax/source/js/_app/${item}.js`).toString();
68
+ text += fs.readFileSync(`node_modules/hexo-theme-shokax/source/js/_app/${item}.js`).toString();
69
69
  }
70
70
  });
71
71
  if (!theme.experiments?.noPlayer) {
72
- if (hexo_fs_1.default.existsSync('themes/shokaX/source/js/_app/player.js')) {
73
- text += hexo_fs_1.default.readFileSync('themes/shokaX/source/js/_app/player.js').toString();
72
+ if (fs.existsSync('themes/shokaX/source/js/_app/player.js')) {
73
+ text += fs.readFileSync('themes/shokaX/source/js/_app/player.js').toString();
74
74
  }
75
75
  else {
76
- text += hexo_fs_1.default.readFileSync('node_modules/hexo-theme-shokax/source/js/_app/player.js').toString();
76
+ text += fs.readFileSync('node_modules/hexo-theme-shokax/source/js/_app/player.js').toString();
77
77
  }
78
78
  }
79
79
  if (theme.fireworks && theme.fireworks.enable) {
80
- if (hexo_fs_1.default.existsSync('themes/shokaX/source/js/_app/fireworks.js')) {
81
- text += hexo_fs_1.default.readFileSync('themes/shokaX/source/js/_app/fireworks.js').toString();
80
+ if (fs.existsSync('themes/shokaX/source/js/_app/fireworks.js')) {
81
+ text += fs.readFileSync('themes/shokaX/source/js/_app/fireworks.js').toString();
82
82
  }
83
83
  else {
84
- text += hexo_fs_1.default.readFileSync('node_modules/hexo-theme-shokax/source/js/_app/fireworks.js').toString();
84
+ text += fs.readFileSync('node_modules/hexo-theme-shokax/source/js/_app/fireworks.js').toString();
85
85
  }
86
86
  siteConfig.fireworks = theme.fireworks.color || ['rgba(255,182,185,.9)', 'rgba(250,227,217,.9)', 'rgba(187,222,214,.9)', 'rgba(138,198,209,.9)'];
87
87
  }
@@ -1,9 +1,6 @@
1
1
  'use strict';
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const hexo_fs_1 = __importDefault(require("hexo-fs"));
3
+ const fs = require("hexo-fs");
7
4
  const prepareQuery = (categories, parent) => {
8
5
  const query = {
9
6
  parent: undefined
@@ -63,7 +60,7 @@ hexo.extend.helper.register('_categories', function () {
63
60
  categories.forEach((cat, i) => {
64
61
  const child = prepareQuery(categories, cat._id);
65
62
  const cover = 'source/_posts' + cat.path.replace(this.config.category_dir, '') + 'cover.jpg';
66
- if (hexo_fs_1.default.existsSync(cover)) {
63
+ if (fs.existsSync(cover)) {
67
64
  const className = cat.slug.split('/');
68
65
  className.pop();
69
66
  cat.class = className.join(' ');
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_fs_1 = __importDefault(require("node:fs"));
7
+ function getContent(post) {
8
+ return post?.raw ?? post?._content ?? post.content;
9
+ }
10
+ let db;
11
+ function postMessage(path, content, dbPath, startMessage) {
12
+ if (node_fs_1.default.existsSync('summary.json')) {
13
+ db = JSON.parse(node_fs_1.default.readFileSync('summary.json'));
14
+ }
15
+ else {
16
+ db = {};
17
+ }
18
+ const config = hexo.theme.config.summary;
19
+ if (config.enable) {
20
+ if (typeof db?.[path] !== 'undefined' && typeof db?.[path]?.[dbPath] !== 'undefined') {
21
+ return db[path][dbPath];
22
+ }
23
+ else {
24
+ if (typeof db?.[path] === 'undefined') {
25
+ db[path] = {};
26
+ }
27
+ else {
28
+ db[path][dbPath] = '';
29
+ }
30
+ }
31
+ if (config.mode === 'openai') {
32
+ const request = () => {
33
+ fetch(`${config.openai.remote}/v1/chat/completions`, {
34
+ method: 'POST',
35
+ headers: requestHeaders,
36
+ body: JSON.stringify(requestBody)
37
+ }).then((response) => {
38
+ if (!response.ok) {
39
+ throw Error('ERROR: Failed to get summary from Openai API');
40
+ }
41
+ response.json().then((data) => {
42
+ const summary = data.choices[0].message.content;
43
+ try {
44
+ db[path][dbPath] = summary;
45
+ }
46
+ catch (e) {
47
+ db ??= {};
48
+ db[path] ??= {};
49
+ db[path][dbPath] ??= '';
50
+ console.log(db[path]);
51
+ db[path][dbPath] = summary;
52
+ }
53
+ node_fs_1.default.writeFileSync('summary.json', JSON.stringify(db));
54
+ if (node_fs_1.default.existsSync('requested.lock')) {
55
+ node_fs_1.default.unlinkSync('requested.lock');
56
+ }
57
+ return summary;
58
+ });
59
+ });
60
+ };
61
+ const checkTime = () => {
62
+ if (node_fs_1.default.existsSync('request.lock')) {
63
+ if (node_fs_1.default.existsSync('requested.lock')) {
64
+ setTimeout(checkTime, 1000 * 10);
65
+ return;
66
+ }
67
+ node_fs_1.default.writeFileSync('requested.lock', '');
68
+ setTimeout(request, 1000 * 20);
69
+ node_fs_1.default.unlinkSync('request.lock');
70
+ }
71
+ else {
72
+ node_fs_1.default.writeFileSync('request.lock', '');
73
+ request();
74
+ }
75
+ };
76
+ const requestHeaders = {
77
+ 'Content-Type': 'application/json',
78
+ Authorization: `Bearer ${config.openai.apikey}`
79
+ };
80
+ const requestBody = {
81
+ model: 'gpt-3.5-turbo',
82
+ messages: [{ role: 'user', content: `${startMessage} ${content}` }],
83
+ temperature: 0.7
84
+ };
85
+ checkTime();
86
+ }
87
+ else {
88
+ }
89
+ }
90
+ }
91
+ hexo.extend.helper.register('get_summary', (post) => {
92
+ return postMessage(post.path, getContent(post), 'summary', '请为下述文章提供一份200字以内的概括,使用中文回答且尽可能简洁: ');
93
+ });
94
+ hexo.extend.helper.register('get_introduce', () => {
95
+ return hexo.theme.config.summary.introduce;
96
+ });
@@ -14,6 +14,13 @@
14
14
  overflow-x: auto;
15
15
  }
16
16
 
17
+ ul.special::before {
18
+ font-family: ic;
19
+ content: "\e652";
20
+ font-size: x-large;
21
+ padding-left: 1em;
22
+ }
23
+
17
24
  li {
18
25
  position: relative;
19
26
  cursor: pointer;
@@ -27,20 +34,20 @@
27
34
  position: absolute;
28
35
  left: 50%;
29
36
  right: 50%;
30
- top: auto;
37
+ top: 2em;
31
38
  bottom: 0;
32
39
  transition: all .2s ease-in-out;
33
40
  width: auto;
34
41
  height: auto;
35
42
  background: none;
36
- border-radius: 0;
43
+ border-radius: 10px;
37
44
  border-bottom: .125rem solid transparent;
38
45
  }
39
46
 
40
47
  &.active::before {
41
48
  left: 0;
42
49
  right: 0;
43
- border-bottom-color: var(--note-hover, var(--primary-color));
50
+ border-bottom-color: var(--primary-color);
44
51
  }
45
52
  }
46
53
  }
@@ -1,4 +1,4 @@
1
- $mobile-wdith = hexo-config('experiments.mobileWidth')
1
+ $mobile-wdith = unquote(hexo-config('experiments.mobileWidth'))
2
2
 
3
3
  the-transition(duration = .2s, function = ease-in-out, delay = 0s, property = all) {
4
4
  transition:property duration function delay;
@@ -77,9 +77,9 @@ function createCircle(x, y) {
77
77
  };
78
78
  return p;
79
79
  }
80
- function renderParticule(anim) {
81
- for (let i = 0; i < anim.animatables.length; i++) {
82
- anim.animatables[i].target.draw();
80
+ function renderParticule(targets) {
81
+ for (const target of targets) {
82
+ target.draw();
83
83
  }
84
84
  }
85
85
  function animateParticules(x, y) {
@@ -88,31 +88,31 @@ function animateParticules(x, y) {
88
88
  for (let i = 0; i < numberOfParticules; i++) {
89
89
  particules.push(createParticule(x, y));
90
90
  }
91
- anime.timeline().add({
91
+ anime().timeline().add({
92
92
  targets: particules,
93
+ duration: anime.random(1200, 1800),
94
+ easing: 'easeOutExpo',
95
+ update: renderParticule,
93
96
  x: function (p) {
94
97
  return p.endPos.x;
95
98
  },
96
99
  y: function (p) {
97
100
  return p.endPos.y;
98
101
  },
99
- radius: 0.1,
100
- duration: anime.random(1200, 1800),
101
- easing: 'easeOutExpo',
102
- update: renderParticule
102
+ radius: 0.1
103
103
  }).add({
104
104
  targets: circle,
105
+ duration: anime.random(1200, 1800),
106
+ easing: 'easeOutExpo',
107
+ update: renderParticule,
105
108
  radius: anime.random(80, 160),
106
109
  lineWidth: 0,
107
110
  alpha: {
108
111
  value: 0,
109
112
  easing: 'linear',
110
113
  duration: anime.random(600, 800)
111
- },
112
- duration: anime.random(1200, 1800),
113
- easing: 'easeOutExpo',
114
- update: renderParticule
115
- }, 0);
114
+ }
115
+ }).play();
116
116
  }
117
117
  const render = anime({
118
118
  duration: Infinity,
@@ -127,7 +127,7 @@ const hasAncestor = function (node, name) {
127
127
  break;
128
128
  if (node.nodeName === name)
129
129
  return true;
130
- } while (node = node.parentNode);
130
+ } while ((node = node.parentNode) !== null);
131
131
  return false;
132
132
  };
133
133
  document.addEventListener(tap, function (e) {
@@ -61,7 +61,7 @@ Object.assign(HTMLElement.prototype, {
61
61
  }
62
62
  return this.getBoundingClientRect().width;
63
63
  },
64
- top: function () {
64
+ getTop: function () {
65
65
  return this.getBoundingClientRect().top;
66
66
  },
67
67
  left: function () {
@@ -192,7 +192,7 @@ const vendorCss = function (type, condition) {
192
192
  window['css' + type] = true;
193
193
  }
194
194
  };
195
- const transition = (target, type, complete) => {
195
+ const transition = (target, type, complete, begin) => {
196
196
  let animation;
197
197
  let display = 'none';
198
198
  switch (type) {
@@ -236,14 +236,14 @@ const transition = (target, type, complete) => {
236
236
  begin: function (anim) {
237
237
  target.display('block');
238
238
  },
239
- translateX: [100, 0],
239
+ translateX: ['100%', '0%'],
240
240
  opacity: [0, 1]
241
241
  };
242
242
  display = 'block';
243
243
  break;
244
244
  case 'slideRightOut':
245
245
  animation = {
246
- translateX: [0, 100],
246
+ translateX: ['0%', '100%'],
247
247
  opacity: [1, 0]
248
248
  };
249
249
  break;
@@ -255,11 +255,15 @@ const transition = (target, type, complete) => {
255
255
  anime(Object.assign({
256
256
  targets: target,
257
257
  duration: 200,
258
- easing: 'linear'
259
- }, animation)).finished.then(function () {
260
- target.display(display);
261
- complete && complete();
262
- });
258
+ easing: 'linear',
259
+ begin: function () {
260
+ begin && begin();
261
+ },
262
+ complete: function () {
263
+ target.display(display);
264
+ complete && complete();
265
+ }
266
+ }, animation)).play();
263
267
  };
264
268
  const pjaxScript = function (element) {
265
269
  const { text, parentNode, id, className, type, src, dataset } = element;
@@ -292,10 +296,10 @@ const pageScroll = function (target, offset, complete) {
292
296
  targets: typeof offset === 'number' ? target.parentNode : document.scrollingElement,
293
297
  duration: 500,
294
298
  easing: 'easeInOutQuad',
295
- scrollTop: offset || (typeof target === 'number' ? target : (target ? target.top() + document.documentElement.scrollTop - siteNavHeight : 0)),
299
+ scrollTop: offset || (typeof target === 'number' ? target : (target ? target.getTop() + document.documentElement.scrollTop - siteNavHeight : 0)),
296
300
  complete: function () {
297
301
  complete && complete();
298
302
  }
299
303
  };
300
- anime(opt);
304
+ anime(opt).play();
301
305
  };
@@ -72,7 +72,7 @@ const postFancybox = function (p) {
72
72
  $dom.each(p + ' p.gallery', function (element) {
73
73
  const box = document.createElement('div');
74
74
  box.className = 'gallery';
75
- box.attr('data-height', element.attr('data-height') || 220);
75
+ box.attr('data-height', String(element.attr('data-height') || 220));
76
76
  box.innerHTML = element.innerHTML.replace(/<br>/g, '');
77
77
  element.parentNode.insertBefore(box, element);
78
78
  element.remove();
@@ -405,7 +405,7 @@ const tabFormat = function () {
405
405
  target.addClass('active');
406
406
  });
407
407
  box.appendChild(element);
408
- element.attr('data-ready', true);
408
+ element.attr('data-ready', String(true));
409
409
  });
410
410
  };
411
411
  const loadComments = function () {
@@ -616,7 +616,7 @@ const domInit = function () {
616
616
  const pjaxReload = function () {
617
617
  pagePosition();
618
618
  if (sideBar.hasClass('on')) {
619
- transition(sideBar, function () {
619
+ transition(sideBar, 0, function () {
620
620
  sideBar.removeClass('on');
621
621
  menuToggle.removeClass('close');
622
622
  });
@@ -425,7 +425,7 @@ const mediaPlayer = function (t, config) {
425
425
  t.player = {
426
426
  _id: utils.random(999999),
427
427
  group: true,
428
- load: function (newList) {
428
+ load: (newList) => {
429
429
  let d = '';
430
430
  if (newList && newList.length > 0) {
431
431
  if (this.options.rawList !== newList) {
@@ -483,7 +483,7 @@ const mediaPlayer = function (t, config) {
483
483
  }
484
484
  });
485
485
  },
486
- mode: function () {
486
+ mode: () => {
487
487
  const total = playlist.data.length;
488
488
  if (!total || playlist.errnum === total) {
489
489
  return;
@@ -496,7 +496,7 @@ const mediaPlayer = function (t, config) {
496
496
  }
497
497
  playlist.index = index;
498
498
  };
499
- const random = function () {
499
+ const random = () => {
500
500
  const p = utils.random(total);
501
501
  if (playlist.index !== p) {
502
502
  playlist.index = p;
@@ -523,7 +523,7 @@ const mediaPlayer = function (t, config) {
523
523
  }
524
524
  this.init();
525
525
  },
526
- switch: function (index) {
526
+ switch: (index) => {
527
527
  if (typeof index === 'number' &&
528
528
  index !== playlist.index &&
529
529
  playlist.current() &&
@@ -555,7 +555,7 @@ const mediaPlayer = function (t, config) {
555
555
  this.play();
556
556
  }
557
557
  },
558
- play: function () {
558
+ play: () => {
559
559
  NOWPLAYING && NOWPLAYING.player.pause();
560
560
  if (playlist.current().error) {
561
561
  this.mode();
@@ -37,6 +37,8 @@ Vue.createApp({
37
37
  }
38
38
  transition(neko, 1, function () {
39
39
  setTimeout(c, 210);
40
+ }, function () {
41
+ neko.display('block');
40
42
  });
41
43
  }
42
44
  }