hexo-theme-shokax 0.3.12 → 0.4.0-alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. package/README.md +10 -3
  2. package/README_en.MD +13 -5
  3. package/_config.yml +19 -16
  4. package/layout/_mixin/comment.pug +4 -4
  5. package/layout/_mixin/segment.pug +1 -1
  6. package/layout/_partials/head/head.pug +0 -1
  7. package/layout/_partials/post/post.pug +1 -1
  8. package/layout/_partials/post/reward.pug +1 -1
  9. package/layout/_partials/sidebar/overview.pug +1 -1
  10. package/package.json +11 -11
  11. package/scripts/filters/locals.d.ts +1 -0
  12. package/scripts/filters/locals.ts +59 -0
  13. package/scripts/filters/post.d.ts +0 -0
  14. package/scripts/filters/post.js +1 -1
  15. package/scripts/filters/post.ts +6 -0
  16. package/scripts/generaters/archive.d.ts +1 -0
  17. package/scripts/generaters/archive.ts +144 -0
  18. package/scripts/generaters/config.d.ts +1 -0
  19. package/scripts/generaters/config.ts +52 -0
  20. package/scripts/generaters/images.d.ts +1 -0
  21. package/scripts/generaters/images.ts +26 -0
  22. package/scripts/generaters/index.d.ts +1 -0
  23. package/scripts/generaters/index.ts +110 -0
  24. package/scripts/generaters/pages.d.ts +0 -0
  25. package/scripts/generaters/pages.ts +16 -0
  26. package/scripts/generaters/script.d.ts +1 -0
  27. package/scripts/generaters/script.js +25 -6
  28. package/scripts/generaters/script.ts +110 -0
  29. package/scripts/helpers/asset.d.ts +1 -0
  30. package/scripts/helpers/asset.ts +158 -0
  31. package/scripts/helpers/engine.d.ts +1 -0
  32. package/scripts/helpers/engine.ts +171 -0
  33. package/scripts/helpers/list_categories.d.ts +1 -0
  34. package/scripts/helpers/list_categories.ts +104 -0
  35. package/scripts/helpers/summary_ai.d.ts +1 -0
  36. package/scripts/helpers/summary_ai.js +1 -1
  37. package/scripts/helpers/summary_ai.ts +100 -0
  38. package/scripts/helpers/symbols_count_time.d.ts +1 -0
  39. package/scripts/helpers/symbols_count_time.ts +76 -0
  40. package/scripts/plugin/check.d.ts +1 -0
  41. package/scripts/plugin/check.ts +35 -0
  42. package/scripts/plugin/index.d.ts +6 -0
  43. package/scripts/plugin/index.ts +52 -0
  44. package/scripts/plugin/lib/injects-point.d.ts +5 -0
  45. package/scripts/plugin/lib/injects-point.ts +20 -0
  46. package/scripts/plugin/lib/injects.d.ts +2 -0
  47. package/scripts/plugin/lib/injects.ts +101 -0
  48. package/scripts/tags/links.d.ts +1 -0
  49. package/scripts/tags/links.ts +75 -0
  50. package/scripts/tags/media.d.ts +1 -0
  51. package/scripts/tags/media.ts +19 -0
  52. package/source/css/_common/components/tags/tabs.styl +3 -1
  53. package/source/css/_common/scaffolding/base.styl +6 -6
  54. package/source/css/_iconfont.styl +4 -0
  55. package/source/js/_app/components/sidebar.ts +237 -0
  56. package/source/js/_app/globals/globalVars.ts +98 -0
  57. package/source/js/_app/globals/handles.ts +122 -0
  58. package/source/js/_app/globals/themeColor.ts +64 -0
  59. package/source/js/_app/globals/thirdparty.ts +63 -0
  60. package/source/js/_app/globals/tools.ts +74 -0
  61. package/source/js/_app/library/anime.ts +109 -0
  62. package/source/js/_app/library/declare.d.ts +117 -0
  63. package/source/js/_app/library/dom.ts +26 -0
  64. package/source/js/_app/library/libtype.d.ts +4 -0
  65. package/source/js/_app/library/loadFile.ts +41 -0
  66. package/source/js/_app/library/proto.ts +143 -0
  67. package/source/js/_app/library/scriptPjax.ts +72 -0
  68. package/source/js/_app/library/storage.ts +12 -0
  69. package/source/js/_app/library/vue.ts +60 -0
  70. package/source/js/_app/page/common.ts +42 -0
  71. package/source/js/_app/page/fancybox.ts +70 -0
  72. package/source/js/_app/page/post.ts +265 -0
  73. package/source/js/_app/page/search.ts +129 -0
  74. package/source/js/_app/page/tab.ts +59 -0
  75. package/source/js/_app/pjax/domInit.ts +95 -0
  76. package/source/js/_app/pjax/refresh.ts +75 -0
  77. package/source/js/_app/pjax/siteInit.ts +67 -0
  78. package/source/js/_app/player.ts +798 -0
  79. package/source/css/twikoo.css +0 -2002
  80. package/source/js/_app/components/sidebar.js +0 -210
  81. package/source/js/_app/fireworks.js +0 -10
  82. package/source/js/_app/globals/globalVars.js +0 -80
  83. package/source/js/_app/globals/handles.js +0 -138
  84. package/source/js/_app/globals/themeColor.js +0 -62
  85. package/source/js/_app/globals/thirdparty.js +0 -71
  86. package/source/js/_app/globals/tools.js +0 -92
  87. package/source/js/_app/library/anime.js +0 -109
  88. package/source/js/_app/library/dom.js +0 -34
  89. package/source/js/_app/library/loadFile.js +0 -36
  90. package/source/js/_app/library/proto.js +0 -163
  91. package/source/js/_app/library/scriptPjax.js +0 -70
  92. package/source/js/_app/library/storage.js +0 -12
  93. package/source/js/_app/library/vue.js +0 -53
  94. package/source/js/_app/page/comment.js +0 -23
  95. package/source/js/_app/page/common.js +0 -41
  96. package/source/js/_app/page/fancybox.js +0 -65
  97. package/source/js/_app/page/post.js +0 -244
  98. package/source/js/_app/page/search.js +0 -118
  99. package/source/js/_app/page/tab.js +0 -53
  100. package/source/js/_app/pjax/domInit.js +0 -76
  101. package/source/js/_app/pjax/refresh.js +0 -53
  102. package/source/js/_app/pjax/siteInit.js +0 -49
  103. package/source/js/_app/player.js +0 -774
package/README.md CHANGED
@@ -1,18 +1,25 @@
1
- # 公告
1
+ # 📣 公告
2
2
  [关于ShokaX markdown扩展特性的讨论](https://github.com/theme-shoka-x/hexo-theme-shokaX/discussions/177) \
3
3
  [关于删除部分评论系统的讨论](https://github.com/theme-shoka-x/hexo-theme-shokaX/discussions/175)
4
+
4
5
  # hexo-theme-shokaX
5
6
  ![LICENSE]( https://img.shields.io/github/license/theme-shoka-x/hexo-theme-shokaX)
6
7
  ![stars](https://img.shields.io/github/stars/theme-shoka-x/hexo-theme-shokaX)
7
8
  ![version](https://shields.io/npm/v/hexo-theme-shokax)
8
9
  ![build](https://img.shields.io/github/actions/workflow/status/theme-shoka-x/hexo-theme-shokaX/build-theme.yml)
9
10
 
10
- 语言(language): 简体中文 | [English](./README_en.MD) \
11
+ #### 语言(language): 简体中文 | [English](./README_en.MD) \
11
12
  此项目是shoka的一个二次开发版(算精神续作),致力于提高性能和优化魔改体验 \
12
13
  诞生原因是目前shoka已经两年没有更新了,积压了大量BUG和功能请求。
13
14
 
14
15
  shokaX的社区资源导航和插件仓库为[awesome-shokaX](https://github.com/theme-shoka-x/awesome-shokaX)
15
16
 
17
+ ## 技术栈
18
+ ![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white)
19
+ ![Vue.js](https://img.shields.io/badge/vuejs-%2335495e.svg?style=for-the-badge&logo=vuedotjs&logoColor=%234FC08D)
20
+ ![Pug](https://img.shields.io/badge/Pug-FFF?style=for-the-badge&logo=pug&logoColor=A86454)
21
+ ![Stylus](https://img.shields.io/badge/stylus-%23ff6347.svg?style=for-the-badge&logo=stylus&logoColor=white)
22
+
16
23
  ## 💬 和shoka的区别
17
24
  原先shoka使用了javascript+Native+nunjucks的技术 \
18
25
  而shokaX则使用了typescript+Vue 3+Pug的技术搭配 \
@@ -61,7 +68,7 @@ SXC install shokaX
61
68
  - [Typescript 中文网](https://www.tslang.cn/docs/home.html)
62
69
  - [Easy hexo](https://easyhexo.com/)
63
70
 
64
- # 许可证
71
+ # [许可证](https://github.com/theme-shoka-x/hexo-theme-shokaX/blob/main/LICENSE)
65
72
  许可证: AGPL 3 or later
66
73
 
67
74
  ## 特别说明
package/README_en.MD CHANGED
@@ -7,12 +7,18 @@
7
7
  ![version](https://shields.io/npm/v/hexo-theme-shokax)
8
8
  ![build](https://img.shields.io/github/actions/workflow/status/theme-shoka-x/hexo-theme-shokaX/build-theme.yml)
9
9
 
10
- Language: [简体中文](./README.md) | English \
10
+ #### Language: [简体中文](./README.md) | English \
11
11
  This project is a fork (spiritual successor) of Shoka, aimed at improving performance and optimizing the modified experience. \
12
12
  The reason for its creation is that Shoka has not been updated for two years, accumulating a large number of bugs and feature requests.
13
13
 
14
14
  The community resource guide and plugin repository for shokaX are available at [awesome-shokaX](https://github.com/theme-shoka-x/awesome-shokaX)
15
15
 
16
+ ## Technology Stack
17
+ ![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white)
18
+ ![Vue.js](https://img.shields.io/badge/vuejs-%2335495e.svg?style=for-the-badge&logo=vuedotjs&logoColor=%234FC08D)
19
+ ![Pug](https://img.shields.io/badge/Pug-FFF?style=for-the-badge&logo=pug&logoColor=A86454)
20
+ ![Stylus](https://img.shields.io/badge/stylus-%23ff6347.svg?style=for-the-badge&logo=stylus&logoColor=white)
21
+
16
22
  ## 💬 Differences from Shoka
17
23
  The original Shoka used a combination of JavaScript + Native + Nunjucks technologies. \
18
24
  ShokaX, on the other hand, uses TypeScript + Vue 3 + Pug technologies and has changed many hard-to-access CDN links.
@@ -35,7 +41,7 @@ Notes:
35
41
  ## 🔧 How to Install
36
42
  Note: This project requires node.js 18.x or higher to run. \
37
43
  It is recommended to use [ShokaX-CLI](https://github.com/zkz098/shokaX-CLI) \
38
- [Click here](https://docs.kaitaku.xyz/guide/#%E9%85%8D%E7%BD%AE%E4%B8%BB%E9%A2%98) for the next configuration steps.
44
+ [Click here](https://docs.kaitaku.xyz/en/guide/) for the next configuration steps.
39
45
 
40
46
  ## 📚 Sub-projects
41
47
  - [ShokaX docs](https://github.com/theme-shoka-x/shokaX-docs) ShokaX Theme Documentation (work in progress, contributions welcome!)
@@ -48,13 +54,15 @@ It is recommended to use [ShokaX-CLI](https://github.com/zkz098/shokaX-CLI) \
48
54
  [ShokaX Official Development Documentation](https://docs.kaitaku.xyz/develop/basic/)
49
55
 
50
56
  Recommended reading for contributing:
51
- - [Hexo Official Documentation](https://hexo.io/zh-cn/docs/templates)
52
- - [Stylus Chinese Documentation](http://stylus.bootcss.com/)
57
+ - [Hexo Official Documentation]([https://hexo.io/zh-cn/docs/templates](https://hexo.io/docs/templates.html))
58
+ - [Stylus Documentation](https://stylus-lang.com/)
59
+ - [Stylus Chinese Documentation](https://stylus.bootcss.com/)
53
60
  - [Pug Template Engine Chinese Documentation](https://www.pugjs.cn/api/getting-started.html)
61
+ - [TypeScript Documentation](https://www.typescriptlang.org/docs/)
54
62
  - [TypeScript Chinese Documentation](https://www.tslang.cn/docs/home.html)
55
63
  - [Easy Hexo](https://easyhexo.com/)
56
64
 
57
- # License
65
+ # [License](https://github.com/theme-shoka-x/hexo-theme-shokaX/blob/main/LICENSE)
58
66
  License: AGPL 3 or later
59
67
 
60
68
  ## Special Note
package/_config.yml CHANGED
@@ -21,8 +21,6 @@ pwa:
21
21
 
22
22
  # 实验性特性
23
23
  experiments:
24
- noIE: true # TODO 阻止IE浏览器访问(ShokaX不支持IE的任何版本)
25
- noPlayer: false # 禁用音乐播放器
26
24
  gradient: false # 使用CSS渐变作为文章封面
27
25
  fixedCover: "" # 主页面cover(为空则使用bing随机图片)
28
26
  debug: false # 使用debug模式启动
@@ -32,6 +30,17 @@ experiments:
32
30
  # 具体见https://docs.kaitaku.xyz/guide/theme.html#%E9%95%BF%E6%96%87%E7%AB%A0%E4%BC%98%E5%8C%96
33
31
  mobileWidth: 820px # 移动版和桌面版导航栏最短切换长度
34
32
 
33
+ # ShokaX 模块化分包引入设置
34
+ # 请关闭所有不使用的模块以优化主题 js 体积和性能
35
+ modules:
36
+ player: true # 启用音乐播放器
37
+ fireworks: true # 启用鼠标点击烟花特效
38
+ unlazyHash: false # 启用unlazy hash预览图支持
39
+ visibilityListener: true # 启用可见度监听器
40
+ tabs: true # 启用选项卡扩展支持,如需开启 summary 功能请一并开启
41
+ quiz: true # 启用文章内问题扩展支持
42
+ fancybox: true # 启用 fancybox 支持(不建议禁用)
43
+
35
44
  # 优化性能区
36
45
  performance:
37
46
  # 使用preconnect预加载的网址(不建议超过三个)
@@ -39,15 +48,11 @@ performance:
39
48
  - "https://lf9-cdn-tos.bytecdntp.com"
40
49
  # 使用dns-prefetch预解析的网址
41
50
  dnsPrefetch:
42
- - "https://cdn.jsdelivr.net"
43
- - "https://unpkg.com"
44
51
 
45
52
  playerAPI: "https://api.injahow.cn" # 结尾不带/,只填写域名
46
53
  # 如果条件允许,请参考 https://github.com/injahow/meting-api 自建API
47
54
  # 使用vercel自行部署,请参考: https://github.com/xizeyoupan/Meting-API
48
55
 
49
- disableVL: false # 禁用可见度监听
50
-
51
56
  icon:
52
57
  favicon: "/favicon.ico"
53
58
  apple_touch_icon: "/apple-touch-icon.png"
@@ -77,7 +82,7 @@ loader:
77
82
 
78
83
  # 使用polyfill.io自动处理浏览器兼容问题
79
84
  polyfill:
80
- enable: true
85
+ enable: false
81
86
  features:
82
87
  - default
83
88
  - fetch
@@ -155,9 +160,9 @@ font:
155
160
  external: true
156
161
  family: Inconsolata
157
162
 
158
- # project of https://www.iconfont.cn/
159
- # //at.alicdn.com/t/font_1832207_c8i9n1ulxlt.css => 1832207_c8i9n1ulxlt
160
- iconfont: "1832207_igi8uaupcus"
163
+ # //at.alicdn.com/t/c/font_4415496_59g1326wajd.css => 4415496_59g1326wajd
164
+ # 自定义iconfont图标参见文档教程
165
+ iconfont: "4415496_59g1326wajd"
161
166
 
162
167
  menu:
163
168
  home: / || home
@@ -175,9 +180,9 @@ menu:
175
180
  # https://twikoo.js.org
176
181
  twikoo:
177
182
  enable: false
178
- link: "https://cdn.staticfile.org/twikoo/1.6.10/twikoo.nocss.min.js"
183
+ link: "https://cdn.staticfile.org/twikoo/1.6.30/twikoo.all.min.js"
179
184
  mode: vercel # vercel或tencent
180
- envId: "https://114514.foo.bar" # twikoo环境ID,vercel填地址
185
+ envId: "https://example.com" # twikoo环境ID,vercel填地址
181
186
  region:
182
187
 
183
188
  # https://waline.js.org/
@@ -212,8 +217,6 @@ summary:
212
217
  openai:
213
218
  remote: "https://api.openai.com"
214
219
  apikey: "key"
215
- custom:
216
- remote: "http://localhost:8000"
217
220
 
218
221
 
219
222
  # Social Links
@@ -222,7 +225,7 @@ summary:
222
225
  # Value before `||` delimiter is the target permalink,
223
226
  # secend value is the name of Font icon.
224
227
  social:
225
- # github: https://github.com/name || github || "#191717"
228
+ github: https://github.com/name || github || "#191717"
226
229
  #google: https://plus.google.com/yourname || google
227
230
  #twitter: https://twitter.com/yourname || twitter || "#00aff0"
228
231
  #zhihu: https://www.zhihu.com/people/yourname || zhihu || "#1e88e5"
@@ -366,7 +369,7 @@ vendors:
366
369
  # mouse_firework: npm_webcache|mouse-firework@0.0.4/dist/index.umd.js
367
370
  async_js:
368
371
  fancybox: bytedance|??jquery/3.5.1/jquery.min.js,fancybox/3.5.7/jquery.fancybox.min.js,justifiedGallery/3.8.1/js/jquery.justifiedGallery.min.js
369
- copy_tex: npm_webcache|katex@0.16.7/contrib/copy-tex.min.js
372
+ copy_tex: npm_webcache|katex@0.16.7/dist/contrib/copy-tex.min.js
370
373
  css:
371
374
  katex: npm_webcache|katex@0.16.7/dist/katex.min.css
372
375
  comment: css/comment.css
@@ -3,17 +3,17 @@ mixin CommentRender()
3
3
  - var tk = theme?.twikoo?.enable,wl = theme?.waline?.enable
4
4
  if page.comment !== false && !theme.experiments.disableThemeComment
5
5
  if tk
6
- div(class="wrap" id="tcomments")
6
+ div(class="wrap" id="comments")
7
7
  script(type="text/javascript" data-pjax).
8
8
  setTimeout(function () {
9
9
  twikoo.init({
10
10
  envId: '#{ theme.twikoo.envId }',
11
- el: '#tcomments',
11
+ el: '#comments',
12
12
  region: '#{theme.twikoo.region}'
13
13
  })
14
14
  }, 1000)
15
15
  else if wl
16
- div(class="wrap" id="wcomments")
16
+ div(class="wrap" id="comments")
17
17
  - var locale = JSON.stringify(theme.waline.locale)
18
18
  - var emoji = JSON.stringify(theme.waline.emoji)
19
19
  - var meta = JSON.stringify(theme.waline.meta)
@@ -23,7 +23,7 @@ mixin CommentRender()
23
23
 
24
24
  setTimeout(function () {
25
25
  init({
26
- el: '#wcomments',
26
+ el: '#comments',
27
27
  serverURL: '#{theme.waline.serverURL.replace(/\/+$/, '')}',
28
28
  lang: '#{theme.waline.lang}',
29
29
  locale: !{locale},
@@ -11,7 +11,7 @@ mixin SMRender(item)
11
11
  div(class="cover" style=`background: linear-gradient(to bottom right, ${random_color()}, ${random_color()});`)
12
12
  else
13
13
  div(class="cover")
14
- != _url(link1, '<img data-src="'+ _cover(item) +'" alt="article cover">', {itemprop: 'url', title: postText})
14
+ != _url(link1, '<img loading="lazy" data-src="'+ _cover(item) +'" alt="article cover">', {itemprop: 'url', title: postText})
15
15
  div(class="info")
16
16
  +PMRender(item)
17
17
  h3
@@ -45,7 +45,6 @@ if fontConfig
45
45
 
46
46
  include pwa.pug
47
47
  if tk
48
- != _css("twikoo.css")
49
48
  script(src=theme.twikoo.link )
50
49
  else if wl
51
50
  link(rel="stylesheet" href="https://npm.webcache.cn/@waline/client@v2/dist/waline.css" media="none" onload="this.media='all'")
@@ -11,7 +11,7 @@ article(itemscope itemtype="http://schema.org/Article" class="post block" lang=t
11
11
  if post.photos && post.photos.length
12
12
  div(class="gallery" itemscope itemtype="http://schema.org/ImageGallery")
13
13
  each photo in post.photos
14
- img(data-src=_image_url(photo, post.path) itemprop="contentUrl")
14
+ img(loading="lazy" data-src=_image_url(photo, post.path) itemprop="contentUrl")
15
15
  if theme.summary.enable && page.layout === 'post'
16
16
  div(class='tabs' id='summary')
17
17
  div(class="show-btn")
@@ -13,6 +13,6 @@ if page.reward !== false
13
13
  else
14
14
  - var translation = name
15
15
  div
16
- img(data-src=`${url_for(theme.statics + theme.assets + image) }` alt=`${ author } ${ translation }`)
16
+ img(loading="lazy" data-src=`${url_for(theme.statics + theme.assets + image) }` alt=`${ author } ${ translation }`)
17
17
  p
18
18
  != translation
@@ -1,5 +1,5 @@
1
1
  div(class="author" itemprop="author" itemscope itemtype="http://schema.org/Person")
2
- img(class="image" itemprop="image" alt=author
2
+ img(loading="lazy" class="image" itemprop="image" alt=author
3
3
  data-src=url_for(theme.statics + theme.assets + '/'+ theme.sidebar.avatar))
4
4
  p(class="name" itemprop="name")
5
5
  != author
package/package.json CHANGED
@@ -1,44 +1,44 @@
1
1
  {
2
2
  "name": "hexo-theme-shokax",
3
- "version": "0.3.12",
3
+ "version": "0.4.0-alpha.1",
4
4
  "description": "a hexo theme based on shoka",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/theme-shoka-x/hexo-theme-shokaX",
7
7
  "author": "zkz098",
8
8
  "license": "AGPL-3.0-or-later",
9
+ "packageManager": "pnpm@8.14.1",
9
10
  "scripts": {
10
11
  "test": "tsc --build --verbose",
11
- "build": "cd ./source && tsc --build --verbose && cd ../scripts && tsc --build --verbose"
12
+ "build": "cd ./scripts && tsc --build --verbose"
12
13
  },
13
14
  "devDependencies": {
14
15
  "@types/fancybox": "^3.5.6",
15
16
  "@types/jquery": "^3.5.29",
16
17
  "@types/js-yaml": "^4.0.9",
17
- "@types/lozad": "^1.16.4",
18
- "@types/node": "^20.11.5",
19
- "@typescript-eslint/eslint-plugin": "^6.19.0",
20
- "@typescript-eslint/parser": "^6.19.0",
18
+ "@types/node": "^20.11.10",
19
+ "@typescript-eslint/eslint-plugin": "^6.20.0",
20
+ "@typescript-eslint/parser": "^6.20.0",
21
21
  "eslint": "^8.56.0",
22
22
  "eslint-config-standard": "~17",
23
23
  "eslint-plugin-import": "^2.29.1",
24
24
  "eslint-plugin-n": "^16.6.2",
25
25
  "eslint-plugin-promise": "^6.1.1",
26
26
  "eslint-plugin-vue": "^9.20.1",
27
- "instantsearch.js": "^4.64.0",
27
+ "instantsearch.js": "^4.64.1",
28
28
  "typescript": "^5.3.3",
29
29
  "vue": "^3.4.15"
30
30
  },
31
31
  "dependencies": {
32
- "esbuild": "^0.19.11",
32
+ "esbuild": "^0.20.0",
33
33
  "hexo": "7.0.0",
34
34
  "hexo-fs": "^4.1.1",
35
35
  "hexo-pagination": "^3.0.0",
36
36
  "hexo-util": "^3.2.0",
37
37
  "js-yaml": "^4.1.0",
38
- "lozad": "^1.16.0",
39
- "mouse-firework": "^0.0.4",
38
+ "mouse-firework": "^0.0.5",
40
39
  "theme-shokax-anime": "^0.0.6",
41
- "theme-shokax-pjax": "^0.0.3"
40
+ "theme-shokax-pjax": "^0.0.3",
41
+ "unlazy": "^0.10.4"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=18.0.0"
@@ -0,0 +1 @@
1
+ declare const fmtNum: (num: any) => any;
@@ -0,0 +1,59 @@
1
+
2
+ // @ts-ignore
3
+ const fmtNum = (num) => {
4
+ return num < 10 ? '0' + num : num
5
+ }
6
+
7
+ hexo.extend.filter.register('template_locals', (locals:localsPlus) => {
8
+ const { config } = hexo
9
+ const { __, theme } = locals
10
+ // @ts-ignore
11
+ const { i18n } = hexo.theme
12
+
13
+ const pangu = {
14
+ spacing: (data) => {
15
+ return data
16
+ }
17
+ }
18
+
19
+ // Language & Config
20
+ // 根据主题配置的 Creative Commons 许可证生成链接
21
+ locals.alternate = theme.alternate
22
+ locals.title = pangu.spacing(__('title') !== 'title' ? __('title') : config.title)
23
+ locals.subtitle = pangu.spacing(__('subtitle') !== 'subtitle' ? __('subtitle') : config.subtitle)
24
+ locals.author = __('author') !== 'author' ? __('author') : config.author
25
+ locals.description = pangu.spacing(__('description') !== 'description' ? __('description') : config.description)
26
+ locals.languages = [...i18n.languages]
27
+ locals.languages.splice(locals.languages.indexOf('default'), 1)
28
+ locals.page.lang = locals.page.lang || locals.page.language
29
+ locals.hostname = new URL(config.url).hostname || config.url
30
+
31
+ // Creative Commons
32
+ // 根据主题配置的 Creative Commons 许可证生成链接
33
+ if (theme.creative_commons.license === 'zero') {
34
+ locals.ccURL = 'https://creativecommons.org/' + 'publicdomain/zero/1.0/' + (theme.creative_commons.language || '')
35
+ } else {
36
+ locals.ccURL = 'https://creativecommons.org/' + 'licenses/' + theme.creative_commons.license + '/4.0/' + (theme.creative_commons.language || '')
37
+ }
38
+
39
+ if (locals.page.title) {
40
+ locals.page.title = pangu.spacing(locals.page.title)
41
+ }
42
+ locals.page.lastcat = ''
43
+ if (locals.page.categories) {
44
+ locals.page.categories.map((cat) => {
45
+ if (cat.name) {
46
+ cat.name = locals.page.lastcat = pangu.spacing(cat.name)
47
+ }
48
+ return cat
49
+ })
50
+ }
51
+
52
+ if (locals.page.category) {
53
+ locals.page.title = pangu.spacing(locals.page.category)
54
+ }
55
+
56
+ if (locals.page.month) {
57
+ locals.page.month = fmtNum(locals.page.month)
58
+ }
59
+ })
File without changes
@@ -1,5 +1,5 @@
1
1
  /* global hexo */
2
2
  hexo.extend.filter.register('after_post_render', (data) => {
3
3
  // 使用正则表达式将<img>标签的src属性替换为data-src属性
4
- data.content = data.content.replace(/(<img[^>]*) src=/img, '$1 data-src=');
4
+ data.content = data.content.replace(/(<img[^>]*) src=/img, '$1 loading="lazy" data-src=');
5
5
  }, 0);
@@ -0,0 +1,6 @@
1
+ /* global hexo */
2
+
3
+ hexo.extend.filter.register('after_post_render', (data) => {
4
+ // 使用正则表达式将<img>标签的src属性替换为data-src属性
5
+ data.content = data.content.replace(/(<img[^>]*) src=/img, '$1 loading="lazy" data-src=')
6
+ }, 0)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,144 @@
1
+ /* global hexo */
2
+ 'use strict'
3
+
4
+ // @ts-ignore
5
+ import pagination from 'hexo-pagination'
6
+
7
+ // @ts-ignore
8
+ const fmtNum = num => {
9
+ return num < 10 ? '0' + num : num
10
+ }
11
+
12
+ if (!(hexo.config.archive && hexo.config.archive.enabled === false)) {
13
+ // when archive disabled pagination, per_page should be 0.
14
+ let per_page
15
+
16
+ if (hexo.config.archive === 1) {
17
+ per_page = 0
18
+ } else if (typeof hexo.config.per_page === 'undefined') {
19
+ per_page = 10
20
+ } else {
21
+ per_page = hexo.config.per_page
22
+ }
23
+
24
+ hexo.config.archive_generator = Object.assign({
25
+ per_page,
26
+ yearly: true,
27
+ monthly: true,
28
+ daily: false
29
+ }, hexo.config.archive_generator)
30
+
31
+ hexo.extend.generator.register('archive', function (locals) {
32
+ const config = hexo.config
33
+ let archiveDir = config.archive_dir
34
+ const paginationDir = config.pagination_dir || 'page'
35
+ // @ts-ignore
36
+ const allPosts = locals.posts.sort(config.archive_generator.order_by || '-date')
37
+ const perPage = config.archive_generator.per_page
38
+ let result = []
39
+
40
+ if (!allPosts.length) return
41
+
42
+ if (archiveDir[archiveDir.length - 1] !== '/') archiveDir += '/'
43
+
44
+ function generate (path, posts, options?) {
45
+ options = options || {}
46
+ options.archive = true
47
+
48
+ result = result.concat(pagination(path, posts, {
49
+ perPage: path === archiveDir ? 0 : perPage,
50
+ layout: ['archive', 'index'],
51
+ format: paginationDir + '/%d/',
52
+ data: options
53
+ }))
54
+ }
55
+
56
+ generate(archiveDir, allPosts)
57
+
58
+ if (!config.archive_generator.yearly) return result
59
+
60
+ const posts = {}
61
+
62
+ // 按日期对文章进行分类
63
+ allPosts.forEach(post => {
64
+ const date = post.date
65
+ const year = date.year()
66
+ const month = date.month() + 1 // month is started from 0
67
+
68
+ if (!Object.prototype.hasOwnProperty.call(posts, year)) {
69
+ // 13个数组. 第一个数组是给这一年的文章准备的
70
+ // 其他则是各个月份的文章
71
+ posts[year] = [
72
+ [],
73
+ [],
74
+ [],
75
+ [],
76
+ [],
77
+ [],
78
+ [],
79
+ [],
80
+ [],
81
+ [],
82
+ [],
83
+ [],
84
+ []
85
+ ]
86
+ }
87
+
88
+ posts[year][0].push(post)
89
+ posts[year][month].push(post)
90
+ // Daily
91
+ if (config.archive_generator.daily) {
92
+ const day = date.date()
93
+ if (!Object.prototype.hasOwnProperty.call(posts[year][month], 'day')) {
94
+ posts[year][month].day = {}
95
+ }
96
+
97
+ (posts[year][month].day[day] || (posts[year][month].day[day] = [])).push(post)
98
+ }
99
+ })
100
+
101
+ const Query = this.model('Post').Query
102
+ const years = Object.keys(posts)
103
+ let year, data, month, monthData, url
104
+
105
+ // Yearly
106
+ for (let i = 0, len = years.length; i < len; i++) {
107
+ year = +years[i]
108
+ data = posts[year]
109
+ url = archiveDir + year + '/'
110
+ if (!data[0].length) continue
111
+
112
+ generate(url, new Query(data[0]), { year })
113
+
114
+ if (!config.archive_generator.monthly && !config.archive_generator.daily) continue
115
+
116
+ // Monthly
117
+ for (month = 1; month <= 12; month++) {
118
+ monthData = data[month]
119
+ if (!monthData.length) continue
120
+ if (config.archive_generator.monthly) {
121
+ generate(url + fmtNum(month) + '/', new Query(monthData), {
122
+ year,
123
+ month
124
+ })
125
+ }
126
+
127
+ if (!config.archive_generator.daily) continue
128
+
129
+ // Daily
130
+ for (let day = 1; day <= 31; day++) {
131
+ const dayData = monthData.day[day]
132
+ if (!dayData || !dayData.length) continue
133
+ generate(url + fmtNum(month) + '/' + fmtNum(day) + '/', new Query(dayData), {
134
+ year,
135
+ month,
136
+ day
137
+ })
138
+ }
139
+ }
140
+ }
141
+
142
+ return result
143
+ })
144
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ 'use strict'
2
+ /* global hexo */
3
+
4
+ import { deepMerge } from 'hexo-util'
5
+ import fs from 'node:fs'
6
+ import path from 'path'
7
+ import yaml from 'js-yaml'
8
+
9
+ hexo.extend.filter.register('before_generate', () => {
10
+ if (hexo.config.theme_config) {
11
+ // @ts-ignore
12
+ hexo.theme.config = deepMerge(hexo.theme.config, hexo.config.theme_config) as any
13
+ }
14
+
15
+ const data = hexo.locals.get('data')
16
+
17
+ if (data.languages) {
18
+ // @ts-ignore
19
+ const { i18n } = hexo.theme
20
+
21
+ const mergeLang = lang => {
22
+ if (data.languages[lang]) { // @ts-ignore
23
+ i18n.set(lang, deepMerge(i18n.get([lang]), data.languages[lang]))
24
+ }
25
+ }
26
+
27
+ for (const lang of ['en', 'ja', 'zh-CN', 'zh-HK', 'zh-TW']) {
28
+ mergeLang(lang)
29
+ }
30
+ }
31
+
32
+ (hexo.theme.config as any).style = {}
33
+
34
+ for (const style of ['iconfont', 'colors', 'custom']) {
35
+ const custom_file = 'source/_data/' + style + '.styl'
36
+ if (fs.existsSync(custom_file)) {
37
+ hexo.theme.config.style[style] = path.resolve(hexo.base_dir, custom_file)
38
+ }
39
+ }
40
+
41
+ if (data.images && data.images.length > 0) {
42
+ hexo.theme.config.image_list = data.images
43
+ } else {
44
+ hexo.theme.config.image_list = yaml.load(fs.readFileSync(path.join(__dirname, '../../_images.yml'), { encoding: 'utf-8' }))
45
+ }
46
+
47
+ if (fs.existsSync(path.join(__dirname, '../../_images_index.yml'))) {
48
+ hexo.theme.config.index_images = yaml.load(fs.readFileSync(path.join(__dirname, '../../_images_index.yml'), { encoding: 'utf-8' }))
49
+ } else {
50
+ hexo.theme.config.index_images = data.index_images || []
51
+ }
52
+ })
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ /* global hexo */
2
+ 'use strict'
3
+
4
+ // @ts-ignore
5
+ import fs = require('hexo-fs')
6
+
7
+ hexo.extend.generator.register('images', function (locals) {
8
+ const theme = hexo.theme.config
9
+ const dir = 'source/_data/' + theme.assets + '/'
10
+
11
+ if (!fs.existsSync(dir)) { return }
12
+
13
+ const result = []
14
+ const files = fs.listDirSync(dir) as string[]
15
+
16
+ files.forEach((file) => {
17
+ result.push({
18
+ path: theme.assets + '/' + file,
19
+ data: function () {
20
+ return fs.createReadStream(dir + file)
21
+ }
22
+ })
23
+ })
24
+
25
+ return result
26
+ })
@@ -0,0 +1 @@
1
+ export {};