hexo-theme-stellar 1.30.4 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/_config.yml +30 -16
  2. package/_data/icons.yml +3 -3
  3. package/_data/widgets.yml +0 -1
  4. package/layout/_partial/comments/artalk/script.ejs +1 -2
  5. package/layout/_partial/comments/layout.ejs +1 -1
  6. package/layout/_partial/head.ejs +20 -1
  7. package/layout/_partial/main/navbar/ghinfo.ejs +1 -1
  8. package/layout/_partial/scripts/defines.ejs +9 -0
  9. package/layout/_partial/scripts/theme.ejs +3 -3
  10. package/layout/_partial/sidebar/index_leftbar.ejs +9 -9
  11. package/layout/_partial/widgets/ghissues.ejs +1 -1
  12. package/layout/_partial/widgets/ghrepo.ejs +2 -2
  13. package/layout/_partial/widgets/ghuser.ejs +1 -1
  14. package/layout/index.ejs +3 -1
  15. package/layout/layout.ejs +3 -1
  16. package/package.json +4 -2
  17. package/scripts/events/index.js +46 -4
  18. package/scripts/events/lib/fix_image_tags.js +44 -0
  19. package/scripts/events/lib/get_image_ratios.js +88 -0
  20. package/scripts/events/lib/version-check.js +86 -0
  21. package/scripts/helpers/json_ld.js +118 -0
  22. package/scripts/tags/lib/albums.js +2 -1
  23. package/scripts/tags/lib/friends.js +2 -1
  24. package/scripts/tags/lib/ghcard.js +3 -2
  25. package/scripts/tags/lib/image.js +16 -6
  26. package/scripts/tags/lib/posters.js +2 -1
  27. package/scripts/tags/lib/sites.js +2 -1
  28. package/scripts/tags/lib/timeline.js +1 -1
  29. package/scripts/tags/lib/video.js +4 -4
  30. package/source/css/_common/base.styl +1 -2
  31. package/source/css/_common/canonical.styl +32 -0
  32. package/source/css/_common/device.styl +6 -4
  33. package/source/css/_common/highlight.styl +1 -1
  34. package/source/css/_components/layout.styl +11 -10
  35. package/source/css/_components/list.styl +3 -0
  36. package/source/css/_components/main.styl +1 -1
  37. package/source/css/_components/md.styl +4 -2
  38. package/source/css/_components/pages/archives.styl +2 -2
  39. package/source/css/_components/pages/article-story.styl +6 -0
  40. package/source/css/_components/pages/article-tech.styl +1 -1
  41. package/source/css/_components/pages/notebook.styl +1 -1
  42. package/source/css/_components/partial/article-banner.styl +4 -1
  43. package/source/css/_components/partial/footer.styl +1 -1
  44. package/source/css/_components/partial/navbar.styl +2 -1
  45. package/source/css/_components/sidebar/nav-area.styl +1 -1
  46. package/source/css/_components/sidebar/search.styl +44 -21
  47. package/source/css/_components/sidebar/sidebar.styl +22 -18
  48. package/source/css/_components/tag-plugins/banner.styl +1 -1
  49. package/source/css/_components/tag-plugins/button.styl +3 -4
  50. package/source/css/_components/tag-plugins/copy.styl +1 -1
  51. package/source/css/_components/tag-plugins/friends.styl +1 -1
  52. package/source/css/_components/tag-plugins/gallery.styl +6 -0
  53. package/source/css/_components/tag-plugins/image.styl +10 -0
  54. package/source/css/_components/tag-plugins/media.styl +1 -1
  55. package/source/css/_components/tag-plugins/note.styl +1 -1
  56. package/source/css/_components/tag-plugins/override.styl +1 -1
  57. package/source/css/_components/tag-plugins/quot.styl +2 -2
  58. package/source/css/_components/tag-plugins/tabs.styl +4 -3
  59. package/source/css/_components/tag-plugins/timeline.styl +2 -2
  60. package/source/css/_components/tag-plugins/toc.styl +1 -1
  61. package/source/css/_components/widgets/list.styl +1 -3
  62. package/source/css/_components/widgets/markdown.styl +0 -7
  63. package/source/css/_components/widgets/toc.styl +6 -4
  64. package/source/css/_components/widgets/widgets.styl +0 -5
  65. package/source/css/_custom.styl +5 -7
  66. package/source/css/_defines/const.styl +1 -1
  67. package/source/css/_defines/func.styl +9 -5
  68. package/source/css/_defines/theme.styl +4 -15
  69. package/source/css/_plugins/comments/artalk.styl +114 -2
  70. package/source/css/_plugins/comments/twikoo.styl +3 -3
  71. package/source/css/_plugins/index.styl +5 -5
  72. package/source/css/_plugins/lazyload.styl +49 -2
  73. package/source/js/main.js +50 -0
  74. package/source/js/plugins/download-file.js +1 -1
  75. package/source/js/search/local-search.js +163 -151
  76. package/source/js/services/artalk_latest_comment.js +1 -1
  77. package/source/js/services/mdrender.js +0 -1
  78. package/layout/_partial/widgets/search.ejs +0 -0
package/_config.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  ######## Stellar info ########
2
2
  stellar:
3
- version: '1.30.4'
3
+ version: '1.32.0'
4
4
  homepage: 'https://xaoxuu.com/wiki/stellar/'
5
5
  repo: 'https://github.com/xaoxuu/hexo-theme-stellar'
6
6
  main_css: /css/main.css
@@ -13,10 +13,20 @@ preconnect:
13
13
  # - https://gcore.jsdelivr.net
14
14
  # - https://unpkg.com
15
15
 
16
+ # 一旦设置源站地址,非源站地址将不会被SEO收录,并且访问时弹出提示
17
+ # 如果访问地址不在备用站主机列表,则警告信息为非法克隆
18
+ canonical:
19
+ originalHost: # 主站点域名主机,例如 xaoxuu.com
20
+ officialHosts: # 官方主机列表,每行一个,例如 xaoxuu.vercel.app
21
+ - localhost
22
+
16
23
  open_graph:
17
24
  enable: true
18
25
  twitter_id: # for open_graph meta
19
26
 
27
+ structured_data:
28
+ links: [] # your social links.
29
+
20
30
 
21
31
  ######## Sidebar ########
22
32
  # 左上角显示的 logo 区域,包含图标、大标题、副标题
@@ -170,8 +180,6 @@ article:
170
180
  type: tech # tech: 默认技术类文章, story: 图文类文章,文字和段落间增距大
171
181
  # 缩进两个文字宽度,适合文字类博客,可以在 front-matter/topic/wiki 中覆盖此参数
172
182
  indent: # true / false
173
- # 如果没有指定封面,是否根据 tags 作为关键词搜索封面图片?
174
- auto_cover: false # search from https://source.unsplash.com/
175
183
  # 封面图宽高比
176
184
  cover_ratio: 2
177
185
  # 文章内横幅宽高比
@@ -212,6 +220,7 @@ comments:
212
220
  service: # beaudar, utterances, giscus, twikoo, waline, artalk
213
221
  comment_title: 快来参与讨论吧~
214
222
  lazyload: false # true / false
223
+ custom_css: # artalk,twikoo,... 可以为没有全局启用的评论加载自定义样式
215
224
  # beaudar
216
225
  # https://beaudar.lipk.org/
217
226
  beaudar:
@@ -302,10 +311,10 @@ comments:
302
311
  # Artalk
303
312
  # https://artalk.js.org/
304
313
  artalk:
305
- css: https://unpkg.com/artalk@2.8/dist/Artalk.css
306
- js: https://unpkg.com/artalk@2.8/dist/Artalk.js
314
+ css: https://unpkg.com/artalk@2.9/dist/Artalk.css
315
+ js: https://unpkg.com/artalk@2.9/dist/Artalk.js
307
316
  server: # 后端服务地址
308
- placeholder: ''
317
+ site: '' # 站点名称
309
318
  darkMode: auto
310
319
 
311
320
 
@@ -324,9 +333,6 @@ footer:
324
333
  # comments:
325
334
  # icon: '<img src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/social/942ebbf1a4b91.svg"/>'
326
335
  # url: /about/#comments
327
- # theme:
328
- # icon: default:theme
329
- # onclick: 'switchTheme()'
330
336
  sitemap:
331
337
  # '博客':
332
338
  # - '[近期](/)'
@@ -439,7 +445,7 @@ data_services:
439
445
  siteinfo:
440
446
  js: /js/services/siteinfo.js
441
447
  # 设置 api 可以自动提取网页标题、图标,服务部署方法:https://github.com/xaoxuu/site-info-api/
442
- # 接口测试通过后,把按钮的 href 部分替换成 {href} 之后填写到下方,例如:https://api.vlts.cc/site_info/v1?url={href}
448
+ # 接口测试通过后,把按钮的 href 部分替换成 {href} 之后填写到下方,例如:https://api.xaox.cc/site_info/v1?url={href}
443
449
  api:
444
450
  ghinfo:
445
451
  js: /js/services/ghinfo.js
@@ -478,7 +484,7 @@ data_services:
478
484
 
479
485
 
480
486
  # 扩展插件接入方法:(插件名下面用 #plugin# 代替)
481
- # 1. 在这里增加 #plugin# 配置,至少赢含有 enable 字段,默认为空(不启用)
487
+ # 1. 在这里增加 #plugin# 配置,至少应含有 enable 字段,默认为空(不启用)
482
488
  # 2. 新建文件 layout/_plugins/#plugin#.ejs 文件中设置编写加载代码。
483
489
  # 2.1. 在该文件中可以直接使用 conf 来读取用户在【步骤 1】填写的配置字段内容
484
490
  # 2.2. 如果需要引入 css 或 js,可以使用 utils.css(xxx)、utils.js(xxx),具体可参考 layout/_plugins/fancybox.ejs
@@ -498,6 +504,10 @@ plugins:
498
504
  enable: true # [hexo clean && hexo s] is required after changing this value.
499
505
  js: https://gcore.jsdelivr.net/npm/vanilla-lazyload@19.1/dist/lazyload.min.js
500
506
  transition: fade # blur, fade
507
+ fix_ratio: true # true / false # 是否固定宽高比,true 时会在图片上添加 style="aspect-ratio: 16/9;",false 时则不添加,开启此功能会导致增加首次 hexo s 的耗时
508
+ loading_image:
509
+ src: # https://github.githubassets.com/images/mona-loading-dark.gif
510
+ size: 2rem # 图片宽度
501
511
 
502
512
  # https://fancyapps.com/docs/ui/fancybox/
503
513
  # available for {% image xxx %}
@@ -617,7 +627,9 @@ style:
617
627
  card: 16px # 文章内大部分卡片的圆角
618
628
  card-s: 12px # 文章内小型卡片的圆角
619
629
  bar: 8px # 横条类元素的圆角
620
- image: 12px # 图片圆角
630
+ image-l: 24px # 非技术类文章插图圆角
631
+ image: 16px # 技术类文章插图圆角
632
+ image-s: 8px # 评论区图片圆角(部分评论支持)
621
633
  color:
622
634
  # 动态颜色(会根据明暗主题重设明度值,只用关心色相和饱和度即可)
623
635
  background: 'hsl(212 16% 98%)' # 浅色背景颜色
@@ -670,9 +682,11 @@ default:
670
682
  project: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/image/2779789.png
671
683
  banner: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/banner/books.jpg
672
684
  topic: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/image/10433048.png
673
-
685
+ image_onerror: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24'%3E%3C!-- Icon from Solar by 480 Design - https://creativecommons.org/licenses/by/4.0/ --%3E%3Cpath fill='%23F44336' d='M22 12.698c-.002 1.47-.013 2.718-.096 3.743c-.097 1.19-.296 2.184-.74 3.009a4.2 4.2 0 0 1-.73.983c-.833.833-1.893 1.21-3.237 1.39C15.884 22 14.2 22 12.053 22h-.106c-2.148 0-3.83 0-5.144-.177c-1.343-.18-2.404-.557-3.236-1.39c-.738-.738-1.12-1.656-1.322-2.795c-.2-1.12-.236-2.512-.243-4.241Q1.999 12.737 2 12v-.054c0-2.148 0-3.83.177-5.144c.18-1.343.557-2.404 1.39-3.236s1.893-1.21 3.236-1.39c1.168-.157 2.67-.175 4.499-.177a.697.697 0 1 1 0 1.396c-1.855.002-3.234.018-4.313.163c-1.189.16-1.906.464-2.436.994S3.72 5.8 3.56 6.99C3.397 8.2 3.395 9.788 3.395 12v.784l.932-.814a2.14 2.14 0 0 1 2.922.097l3.99 3.99a1.86 1.86 0 0 0 2.385.207l.278-.195a2.79 2.79 0 0 1 3.471.209l2.633 2.37c.265-.557.423-1.288.507-2.32c.079-.972.09-2.152.091-3.63a.698.698 0 0 1 1.396 0' opacity='.5'/%3E%3Cpath fill='%23F44336' fill-rule='evenodd' d='M17.5 11c-2.121 0-3.182 0-3.841-.659S13 8.621 13 6.5s0-3.182.659-3.841S15.379 2 17.5 2s3.182 0 3.841.659S22 4.379 22 6.5s0 3.182-.659 3.841S19.621 11 17.5 11m-1.47-7.03a.75.75 0 1 0-1.06 1.06l1.47 1.47l-1.47 1.47a.75.75 0 0 0 1.06 1.06l1.47-1.47l1.47 1.47a.75.75 0 1 0 1.06-1.06L18.56 6.5l1.47-1.47a.75.75 0 0 0-1.06-1.06L17.5 5.44z' clip-rule='evenodd'/%3E%3C/svg%3E"
674
686
 
675
687
  api_host:
676
- ghapi: https://api.github.com
677
- ghraw: https://raw.githubusercontent.com
678
- gist: https://gist.github.com
688
+ ghapi: api.github.com
689
+ ghraw: raw.githubusercontent.com
690
+ gist: gist.github.com
691
+ # https://github.com/anuraghazra/github-readme-stats
692
+ ghcard: github-readme-stats.vercel.app
package/_data/icons.yml CHANGED
@@ -30,9 +30,9 @@ default:calendar: <svg style="margin-bottom:2px" xmlns="http://www.w3.org/2000/s
30
30
  default:category: <svg style="margin-bottom:1px" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M2 6.95c0-.883 0-1.324.07-1.692A4 4 0 0 1 5.257 2.07C5.626 2 6.068 2 6.95 2c.386 0 .58 0 .766.017a4 4 0 0 1 2.18.904c.144.119.28.255.554.529L11 4c.816.816 1.224 1.224 1.712 1.495a4 4 0 0 0 .848.352C14.098 6 14.675 6 15.828 6h.374c2.632 0 3.949 0 4.804.77c.079.07.154.145.224.224c.77.855.77 2.172.77 4.804V14c0 3.771 0 5.657-1.172 6.828C19.657 22 17.771 22 14 22h-4c-3.771 0-5.657 0-6.828-1.172C2 19.657 2 17.771 2 14z" opacity=".5"/><path fill="currentColor" d="M20 6.238c0-.298-.005-.475-.025-.63a3 3 0 0 0-2.583-2.582C17.197 3 16.965 3 16.5 3H9.988c.116.104.247.234.462.45L11 4c.816.816 1.224 1.224 1.712 1.495a4 4 0 0 0 .849.352C14.098 6 14.675 6 15.829 6h.373c1.78 0 2.957 0 3.798.238"/><path fill="currentColor" fill-rule="evenodd" d="M12.25 10a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75" clip-rule="evenodd"/></svg>
31
31
 
32
32
  # 编辑本文
33
- default:edit: <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M11.943 1.25H13.5a.75.75 0 0 1 0 1.5H12c-2.378 0-4.086.002-5.386.176c-1.279.172-2.05.5-2.62 1.069c-.569.57-.896 1.34-1.068 2.619c-.174 1.3-.176 3.008-.176 5.386s.002 4.086.176 5.386c.172 1.279.5 2.05 1.069 2.62c.57.569 1.34.896 2.619 1.068c1.3.174 3.008.176 5.386.176s4.086-.002 5.386-.176c1.279-.172 2.05-.5 2.62-1.069c.569-.57.896-1.34 1.068-2.619c.174-1.3.176-3.008.176-5.386v-1.5a.75.75 0 0 1 1.5 0v1.557c0 2.309 0 4.118-.19 5.53c-.194 1.444-.6 2.584-1.494 3.479c-.895.895-2.035 1.3-3.48 1.494c-1.411.19-3.22.19-5.529.19h-.114c-2.309 0-4.118 0-5.53-.19c-1.444-.194-2.584-.6-3.479-1.494c-.895-.895-1.3-2.035-1.494-3.48c-.19-1.411-.19-3.22-.19-5.529v-.114c0-2.309 0-4.118.19-5.53c.194-1.444.6-2.584 1.494-3.479c.895-.895 2.035-1.3 3.48-1.494c1.411-.19 3.22-.19 5.529-.19m4.827 1.026a3.503 3.503 0 0 1 4.954 4.953l-6.648 6.649c-.371.37-.604.604-.863.806a5.34 5.34 0 0 1-.987.61c-.297.141-.61.245-1.107.411l-2.905.968a1.492 1.492 0 0 1-1.887-1.887l.968-2.905c.166-.498.27-.81.411-1.107c.167-.35.372-.68.61-.987c.202-.26.435-.492.806-.863zm3.893 1.06a2.003 2.003 0 0 0-2.832 0l-.376.377c.022.096.054.21.098.338c.143.413.415.957.927 1.469a3.875 3.875 0 0 0 1.807 1.025l.376-.376a2.003 2.003 0 0 0 0-2.832m-1.558 4.391a5.397 5.397 0 0 1-1.686-1.146a5.395 5.395 0 0 1-1.146-1.686L11.218 9.95c-.417.417-.58.582-.72.76a3.84 3.84 0 0 0-.437.71c-.098.203-.172.423-.359.982l-.431 1.295l1.032 1.033l1.295-.432c.56-.187.779-.261.983-.358c.251-.12.49-.267.71-.439c.177-.139.342-.302.759-.718z" clip-rule="evenodd"/></svg>
34
- default:upup: <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 12c0-4.714 0-7.071 1.464-8.536C4.93 2 7.286 2 12 2c4.714 0 7.071 0 8.535 1.464C22 4.93 22 7.286 22 12c0 4.714 0 7.071-1.465 8.535C19.072 22 16.714 22 12 22s-7.071 0-8.536-1.465C2 19.072 2 16.714 2 12Z"/><path stroke-linecap="round" stroke-linejoin="round" d="m9 15.5l3-3l3 3m-6-4l3-3l3 3"/></g></svg>
35
- default:tocomment: <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M10.46 1.25h3.08c1.603 0 2.86 0 3.864.095c1.023.098 1.861.3 2.6.752a5.75 5.75 0 0 1 1.899 1.899c.452.738.654 1.577.752 2.6c.095 1.004.095 2.261.095 3.865v1.067c0 1.141 0 2.036-.05 2.759c-.05.735-.153 1.347-.388 1.913a5.75 5.75 0 0 1-3.112 3.112c-.805.334-1.721.408-2.977.43a10.81 10.81 0 0 0-.929.036c-.198.022-.275.054-.32.08c-.047.028-.112.078-.224.232c-.121.166-.258.396-.476.764l-.542.916c-.773 1.307-2.69 1.307-3.464 0l-.542-.916a10.605 10.605 0 0 0-.476-.764c-.112-.154-.177-.204-.224-.232c-.045-.026-.122-.058-.32-.08c-.212-.023-.49-.03-.93-.037c-1.255-.021-2.171-.095-2.976-.429A5.75 5.75 0 0 1 1.688 16.2c-.235-.566-.338-1.178-.389-1.913c-.049-.723-.049-1.618-.049-2.76v-1.066c0-1.604 0-2.86.095-3.865c.098-1.023.3-1.862.752-2.6a5.75 5.75 0 0 1 1.899-1.899c.738-.452 1.577-.654 2.6-.752C7.6 1.25 8.857 1.25 10.461 1.25M6.739 2.839c-.914.087-1.495.253-1.959.537A4.25 4.25 0 0 0 3.376 4.78c-.284.464-.45 1.045-.537 1.96c-.088.924-.089 2.11-.089 3.761v1c0 1.175 0 2.019.046 2.685c.045.659.131 1.089.278 1.441a4.25 4.25 0 0 0 2.3 2.3c.515.214 1.173.294 2.429.316h.031c.398.007.747.013 1.037.045c.311.035.616.104.909.274c.29.17.5.395.682.645c.169.232.342.525.538.856l.559.944a.52.52 0 0 0 .882 0l.559-.944c.196-.331.37-.624.538-.856c.182-.25.392-.476.682-.645c.293-.17.598-.24.909-.274c.29-.032.639-.038 1.037-.045h.032c1.255-.022 1.913-.102 2.428-.316a4.25 4.25 0 0 0 2.3-2.3c.147-.352.233-.782.278-1.441c.046-.666.046-1.51.046-2.685v-1c0-1.651 0-2.837-.089-3.762c-.087-.914-.253-1.495-.537-1.959a4.25 4.25 0 0 0-1.403-1.403c-.464-.284-1.045-.45-1.96-.537c-.924-.088-2.11-.089-3.761-.089h-3c-1.651 0-2.837 0-3.762.089" clip-rule="evenodd"/><path fill="currentColor" d="M9 11a1 1 0 1 1-2 0a1 1 0 0 1 2 0m4 0a1 1 0 1 1-2 0a1 1 0 0 1 2 0m4 0a1 1 0 1 1-2 0a1 1 0 0 1 2 0"/></svg>
33
+ default:edit: <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Solar by 480 Design - https://creativecommons.org/licenses/by/4.0/ --><g fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-width="1.5" d="m16.652 3.455l.649-.649A2.753 2.753 0 0 1 21.194 6.7l-.65.649m-3.892-3.893s.081 1.379 1.298 2.595c1.216 1.217 2.595 1.298 2.595 1.298m-3.893-3.893L10.687 9.42c-.404.404-.606.606-.78.829q-.308.395-.524.848c-.121.255-.211.526-.392 1.068L8.412 13.9m12.133-6.552l-2.983 2.982m-2.982 2.983c-.404.404-.606.606-.829.78a4.6 4.6 0 0 1-.848.524c-.255.121-.526.211-1.068.392l-1.735.579m0 0l-1.123.374a.742.742 0 0 1-.939-.94l.374-1.122m1.688 1.688L8.412 13.9"/><path fill="currentColor" d="M22.75 12a.75.75 0 0 0-1.5 0zM12 2.75a.75.75 0 0 0 0-1.5zM7.376 20.013a.75.75 0 1 0-.752 1.298zm-4.687-2.638a.75.75 0 1 0 1.298-.75zM21.25 12A9.25 9.25 0 0 1 12 21.25v1.5c5.937 0 10.75-4.813 10.75-10.75zM12 1.25C6.063 1.25 1.25 6.063 1.25 12h1.5A9.25 9.25 0 0 1 12 2.75zM6.624 21.311A10.7 10.7 0 0 0 12 22.75v-1.5a9.2 9.2 0 0 1-4.624-1.237zM1.25 12a10.7 10.7 0 0 0 1.439 5.375l1.298-.75A9.2 9.2 0 0 1 2.75 12z"/></g></svg>
34
+ default:upup: <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Solar by 480 Design - https://creativecommons.org/licenses/by/4.0/ --><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5"><path stroke-linejoin="round" d="m9 15.5l3-3l3 3m-6-4l3-3l3 3"/><path d="M7 3.338A9.95 9.95 0 0 1 12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12c0-1.821.487-3.53 1.338-5"/></g></svg>
35
+ default:tocomment: <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Solar by 480 Design - https://creativecommons.org/licenses/by/4.0/ --><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5" d="M8 10.5h8M8 14h5.5M17 3.338A9.95 9.95 0 0 0 12 2C6.477 2 2 6.477 2 12c0 1.6.376 3.112 1.043 4.453c.178.356.237.763.134 1.148l-.595 2.226a1.3 1.3 0 0 0 1.591 1.592l2.226-.596a1.63 1.63 0 0 1 1.149.133A9.96 9.96 0 0 0 12 22c5.523 0 10-4.477 10-10c0-1.821-.487-3.53-1.338-5"/></svg>
36
36
  default:theme: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" fill-rule="evenodd" d="M582.4 326.4c-140.8 0-256 115.2-256 256s115.2 256 256 256 256-115.2 256-256-115.2-256-256-256z m0 448c-70.4 0-131.2-36.8-164.8-92.8 12.8 3.2 27.2 4.8 40 4.8 121.6 0 219.2-99.2 219.2-219.2 0-17.6-1.6-35.2-6.4-52.8 60.8 32 102.4 96 102.4 169.6 1.6 104-84.8 190.4-190.4 190.4zM582.4 262.4c17.6 0 32-14.4 32-32v-128c0-17.6-14.4-32-32-32s-32 14.4-32 32v128c0 17.6 14.4 32 32 32zM262.4 582.4c0-17.6-14.4-32-32-32h-128c-17.6 0-32 14.4-32 32s14.4 32 32 32h128c17.6 0 32-14.4 32-32zM310.4 356.8c6.4 6.4 14.4 9.6 22.4 9.6 8 0 16-3.2 22.4-9.6 12.8-12.8 12.8-32 0-44.8l-91.2-91.2c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l91.2 91.2zM944 220.8c-12.8-12.8-32-12.8-44.8 0l-91.2 91.2c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.4 9.6 22.4 9.6 8 0 16-3.2 22.4-9.6l91.2-91.2c12.8-12.8 12.8-33.6 0-44.8zM310.4 808l-91.2 91.2c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.4 9.6 22.4 9.6 8 0 16-3.2 22.4-9.6l91.2-91.2c12.8-12.8 12.8-32 0-44.8-11.2-11.2-32-11.2-44.8 0z"></path></svg>
37
37
 
38
38
  github:logo: <svg aria-hidden="true" role="img" class="color-icon-primary" viewBox="0 0 16 16" width="1em" height="1em" fill="currentColor" style="display:inline-block;user-select:none;vertical-align:text-bottom;overflow:visible"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>
package/_data/widgets.yml CHANGED
@@ -68,7 +68,6 @@ timeline:
68
68
  title: 近期动态
69
69
  api: # https://api.github.com/repos/xaoxuu/hexo-theme-stellar/issues
70
70
  user: # 默认显示所有人的数据,设置名称可过滤为仅显示某人的数据,多个名称用英文逗号隔开,不要加空格
71
- type: # 默认不用写,如果是友链朋友圈数据请写 fcircle
72
71
  limit: # 默认通过 api 上增加 per_page 来设置,如果是友链朋友圈,可通过这个设置数量
73
72
 
74
73
  latest_comment:
@@ -12,8 +12,7 @@
12
12
  pageKey: path,
13
13
  pageTitle: '<%= page.title %>',
14
14
  server: '<%= theme.comments.artalk.server %>',
15
- placeholder: '<%= theme.comments.artalk.placeholder %>',
16
- site: "<%- config.title %>",
15
+ site: '<%= theme.comments.artalk.site %>',
17
16
  darkMode: '<%= theme.comments.artalk.darkMode %>'
18
17
  });
19
18
  });
@@ -1,6 +1,6 @@
1
1
  <%
2
2
  var cmt = {
3
- service: theme.comments.service
3
+ service: page.comments_service || theme.comments.service
4
4
  };
5
5
  if (cmt.service) {
6
6
  cmt[cmt.service] = Object.assign({}, theme.comments[cmt.service]);
@@ -47,6 +47,10 @@ function generate_keywords() {
47
47
  }
48
48
 
49
49
  function generate_robots() {
50
+ const IS_BACKUP = process.env.IS_BACKUP === 'true';
51
+ if (IS_BACKUP) {
52
+ return '<meta name="robots" content="noindex, nofollow">';
53
+ }
50
54
  if (is_home() == true) {
51
55
  return '';
52
56
  }
@@ -62,6 +66,7 @@ function og_args() {
62
66
  if (page.layout == 'post' && page.cover) {
63
67
  args.twitter_card = 'summary_large_image';
64
68
  }
69
+ args.image = config.avatar || (config.email ? gravatar(config.email) : null);
65
70
  return Object.assign(args, page.open_graph);
66
71
  }
67
72
 
@@ -87,11 +92,25 @@ function custom_inject() {
87
92
  return el;
88
93
  }
89
94
 
95
+ function generate_canonical() {
96
+ const originalHost = theme.canonical.originalHost || '';
97
+ if (originalHost.length > 0) {
98
+ if (is_home()) {
99
+ return `<link rel="canonical" href="https://${originalHost}/">`;
100
+ } else if (page.path?.length > 0) {
101
+ const path = page.path.replace(/index\.html$/, '') || '/';
102
+ return `<link rel="canonical" href="https://${originalHost}/${path}">`;
103
+ }
104
+ }
105
+ return '';
106
+ }
107
+
90
108
  %>
91
109
 
92
110
  <head>
93
111
  <meta charset="utf-8">
94
112
  <meta name="hexo-theme" content="<%- stellar_info('tree') %>" theme-name="<%- stellar_info('name') %>" theme-version="<%- stellar_info('version') %>">
113
+ <%- generate_canonical() %>
95
114
  <%- generate_robots() %>
96
115
  <%- meta_generator() %>
97
116
  <meta http-equiv='x-dns-prefetch-control' content='on' />
@@ -104,7 +123,6 @@ function custom_inject() {
104
123
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
105
124
  <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#000">
106
125
  <meta name="theme-color" content="#f9fafb">
107
-
108
126
  <title><%- generate_title() %></title>
109
127
 
110
128
  <% if (theme.open_graph && theme.open_graph.enable) { %>
@@ -130,5 +148,6 @@ function custom_inject() {
130
148
  <%- css(theme.style.codeblock.highlightjs_theme) %>
131
149
  <% } %>
132
150
 
151
+ <%- json_ld() %>
133
152
  <%- custom_inject() %>
134
153
  </head>
@@ -5,7 +5,7 @@ function layoutDiv() {
5
5
  return ''
6
6
  }
7
7
  return `
8
- <div class="right ghrepo ds-ghinfo" api="${theme.api_host.ghapi}/repos/${repo}">
8
+ <div class="right ghrepo ds-ghinfo" api="https://${theme.api_host.ghapi}/repos/${repo}">
9
9
  <a class="repo-link bold" href="https://github.com/${repo}">
10
10
  ${icon('github:repo')}
11
11
  <span type="text">${repo}</span>
@@ -1,4 +1,13 @@
1
+ <%
2
+ const canonical = theme.canonical || {}
3
+ const encoded = Buffer.from(canonical.originalHost || '').toString('base64');
4
+ const canonicalWithEncoded = Object.assign({}, canonical, {
5
+ encoded: encoded
6
+ });
7
+ %>
8
+
1
9
  <script type="text/javascript">
10
+ window.canonical = <%- JSON.stringify(canonicalWithEncoded) %>;
2
11
  const ctx = {
3
12
  date_suffix: {
4
13
  just: `<%- __('meta.date_suffix.just') %>`,
@@ -6,12 +6,12 @@
6
6
  document.documentElement.setAttribute('data-theme', theme)
7
7
  }
8
8
 
9
- applyThemeToGiscus(theme)
9
+ // applyThemeToGiscus(theme)
10
10
  }
11
11
 
12
+ // FIXME: 这会导致无法使用 preferred_color_scheme 以外的主题
12
13
  const applyThemeToGiscus = (theme) => {
13
- theme = theme === 'auto' ? 'preferred_color_scheme' : theme
14
-
14
+ // theme = theme === 'auto' ? 'preferred_color_scheme' : theme
15
15
  const cmt = document.getElementById('giscus')
16
16
  if (cmt) {
17
17
  // This works before giscus load.
@@ -79,6 +79,15 @@ function layoutWidgets() {
79
79
  var el = '';
80
80
  el += '<div class="widgets">';
81
81
  if (page.leftbar) {
82
+ var search = {}
83
+ if (page.search) {
84
+ search = page.search
85
+ } else if (wiki?.search) {
86
+ search = wiki.search
87
+ } else if (topic?.search) {
88
+ search = topic.search
89
+ }
90
+ el += partial('search', {item: search})
82
91
  page.leftbar.forEach((w, i) => {
83
92
  let name = ''
84
93
  let widget = {}
@@ -141,17 +150,8 @@ function layoutLogo() {
141
150
  }
142
151
 
143
152
  function layoutNavArea() {
144
- var search = {}
145
- if (page.search) {
146
- search = page.search
147
- } else if (wiki?.search) {
148
- search = wiki.search
149
- } else if (topic?.search) {
150
- search = topic.search
151
- }
152
153
  var el = ''
153
154
  el += `<div class="nav-area">`
154
- el += partial('search', {item: search})
155
155
  el += partial('menu', {where: 'sidebar'})
156
156
  el += `</div>`
157
157
  return el
@@ -15,7 +15,7 @@ function layoutDiv() {
15
15
  if (repo == undefined) {
16
16
  return el;
17
17
  }
18
- item.api = theme.api_host.ghapi + '/repos/' + repo + '/issues?per_page=' + item.limit;
18
+ item.api = `https://${theme.api_host.ghapi}/repos/${repo}/issues?per_page=${item.limit}`;
19
19
  if (item.labels) {
20
20
  item.api += '&labels=' + item.labels;
21
21
  }
@@ -19,7 +19,7 @@ function layoutDiv() {
19
19
  el += `<widget class="widget-wrapper${scrollreveal(' ')} ghrepo">`
20
20
  // body
21
21
  el += '<div class="widget-body">';
22
- el += '<div class="items ds-ghinfo" api="' + theme.api_host.ghapi + '/repos/' + repo + '">';
22
+ el += '<div class="items ds-ghinfo" api="https://' + theme.api_host.ghapi + '/repos/' + repo + '">';
23
23
  el += '<a class="repo" href="https://github.com/' + repo + '" target="_blank" rel="external nofollow noopener noreferrer">';
24
24
  el += '<div class="repo-name flex-row">';
25
25
  el += icon('github:repo')
@@ -35,7 +35,7 @@ function layoutDiv() {
35
35
  el += icon('github:fork')
36
36
  el += '<span type="text" id="forks_count"></span>';
37
37
  el += '</div>';
38
- el += '<div class="flex-row ds-ghinfo" index="0" api="' + theme.api_host.ghapi + '/repos/' + repo + '/tags">';
38
+ el += '<div class="flex-row ds-ghinfo" index="0" api="https://' + theme.api_host.ghapi + '/repos/' + repo + '/tags">';
39
39
  el += icon('github:tag')
40
40
  el += '<span type="text" id="latest-tag-name">0</span>';
41
41
  el += '</div>';
@@ -24,7 +24,7 @@ function layoutDiv() {
24
24
 
25
25
  el += `<widget class="widget-wrapper${scrollreveal(' ')} user-card ghuser">`
26
26
  // body
27
- el += '<div class="widget-body ds-ghinfo" api="' + theme.api_host.ghapi + '/users/' + item.username + '">';
27
+ el += '<div class="widget-body ds-ghinfo" api="https://' + theme.api_host.ghapi + '/users/' + item.username + '">';
28
28
  if (item.avatar) {
29
29
  el += '<div class="avatar" ><img no-lazy type="img" id="avatar_url" src="' + config.avatar + '"></div>';
30
30
  }
package/layout/index.ejs CHANGED
@@ -22,7 +22,9 @@ function layout_post_list(partial) {
22
22
  var el = '';
23
23
  el += '<div class="post-list post">';
24
24
  page.posts.each(function(post){
25
- el += layout_post_card('post', post, partial(post));
25
+ if (post.indexing != false) {
26
+ el += layout_post_card('post', post, partial(post));
27
+ }
26
28
  })
27
29
  el += '</div>';
28
30
  return el;
package/layout/layout.ejs CHANGED
@@ -8,7 +8,9 @@ if (['post', 'page', 'wiki', null].includes(page.layout)) {
8
8
  }
9
9
  // 文章类型:技术类文章/文学类文章
10
10
  var article_type = theme.article.type
11
- if (page.type?.length > 0) {
11
+ if (page_type == 'index') {
12
+ article_type = undefined
13
+ } else if (page.type?.length > 0) {
12
14
  article_type = page.type
13
15
  } else if (theme.topic.tree[page.topic]?.type != null) {
14
16
  article_type = theme.topic.tree[page.topic]?.type
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-stellar",
3
- "version": "1.30.4",
3
+ "version": "1.32.0",
4
4
  "description": "Elegant and powerful theme for Hexo.",
5
5
  "main": "package.json",
6
6
  "scripts": {
@@ -21,8 +21,10 @@
21
21
  "url": "https://github.com/xaoxuu/hexo-theme-stellar/issues/"
22
22
  },
23
23
  "dependencies": {
24
+ "cheerio": "^1.1.0",
24
25
  "hexo-renderer-ejs": "^2.0.0",
25
- "hexo-renderer-stylus": "^3.0.1"
26
+ "hexo-renderer-stylus": "^3.0.1",
27
+ "probe-image-size": "^7.2.3"
26
28
  },
27
29
  "homepage": "https://xaoxuu.com/wiki/stellar/",
28
30
  "devDependencies": {
@@ -18,9 +18,51 @@ hexo.on('generateAfter', () => {
18
18
  });
19
19
 
20
20
  hexo.on('ready', () => {
21
+ if (process.env.HEXO_READY === '1') return;
22
+ process.env.HEXO_READY = '1';
23
+ const isClean = ['cl', 'clean'].some(arg => process.argv.includes(arg));
24
+ if (isClean) {
25
+ return;
26
+ }
21
27
  const { version, homepage, repository } = require('../../package.json');
22
- hexo.log.info(`Welcome to Stellar ${version}
23
- DOCS ${homepage}
24
- REPO ${repository.url}
25
- `);
28
+ console.log(``);
29
+
30
+ const line = '------------------------------------------------';
31
+ hexo.log.info(line);
32
+ hexo.log.info(`Welcome to \x1b[33mStellar ${version}\x1b[0m
33
+ \x1b[32mDOCS\x1b[0m ${homepage}
34
+ \x1b[32mREPO\x1b[0m ${repository.url}`);
35
+ hexo.log.info(line);
36
+ console.log(``);
37
+ // version check
38
+ const checkVersion = require('./lib/version-check');
39
+ checkVersion(hexo, { useCache: true });
40
+ });
41
+
42
+
43
+ // 防止重复注册
44
+ let hasRun = false;
45
+
46
+ hexo.extend.filter.register('before_generate', async () => {
47
+ const isDev = ['s', 'server', 'serve'].some(arg => process.argv.includes(arg));
48
+ if (!isDev) {
49
+ return;
50
+ }
51
+
52
+ if (hasRun) return;
53
+ hasRun = true;
54
+
55
+ // 读取主题配置开关
56
+ const enabled = hexo.theme.config.plugins?.lazyload?.fix_ratio === true;
57
+
58
+ const generateImageRatios = require('./lib/get_image_ratios');
59
+ const fixMarkdownImages = require('./lib/fix_image_tags');
60
+
61
+ if (enabled) {
62
+ // 构建前:生成缓存 + 写回 Markdown
63
+ await generateImageRatios(hexo);
64
+ fixMarkdownImages(hexo); // 不用 await,因为是同步的
65
+ }
26
66
  });
67
+
68
+
@@ -0,0 +1,44 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const glob = require('glob');
4
+
5
+ module.exports = (ctx, options) => {
6
+ const mdFiles = glob.sync('source/**/*.md');
7
+
8
+ const ratioMapPath = path.join(__dirname, '../../.cache/image-ratios.json');
9
+ if (!fs.existsSync(ratioMapPath)) {
10
+ return;
11
+ }
12
+ const ratioMap = JSON.parse(fs.readFileSync(ratioMapPath));
13
+
14
+ mdFiles.forEach(file => {
15
+ let content = fs.readFileSync(file, 'utf8');
16
+ let modified = false;
17
+ const relativePath = path.relative(process.cwd(), file);
18
+ const fileRatios = ratioMap[relativePath];
19
+ if (!fileRatios) {
20
+ return;
21
+ }
22
+ content = content.replace(
23
+ /{%\s+image\s+([^\n%]*?)\b(https?:\/\/[^\s%]+)\b([^\n%]*?)%}/g,
24
+ (match, before, url, after) => {
25
+ if (match.includes('ratio:')) return match;
26
+
27
+ const ratio = fileRatios?.[url];
28
+ if (!ratio) return match;
29
+ modified = true;
30
+ const beforeTrim = before ? before.trim() : '';
31
+ if (beforeTrim.length > 0) {
32
+ return `{% image ${before.trim()} ${url} ${after.trim()} ratio:${ratio} %}`;
33
+ } else {
34
+ return `{% image ${url} ${after.trim()} ratio:${ratio} %}`;
35
+ }
36
+ }
37
+ );
38
+
39
+ if (modified) {
40
+ fs.writeFileSync(file, content, 'utf8');
41
+ }
42
+ });
43
+ ctx.log.info('{% image %} 标签的图片长宽比已固定!');
44
+ };
@@ -0,0 +1,88 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const glob = require('glob');
4
+ const probe = require('probe-image-size');
5
+
6
+ const outputPath = path.join(__dirname, '../../.cache/image-ratios.json');
7
+
8
+ // 读取已有缓存
9
+ let cache = fs.existsSync(outputPath)
10
+ ? JSON.parse(fs.readFileSync(outputPath))
11
+ : {};
12
+
13
+ // 提取 Markdown 中的图片链接
14
+ function extractImageUrls(content) {
15
+ const urls = [];
16
+ const tagImgRegex = /{%\s+image\s+[^%]*?\b(https?:\/\/[^\s%]+)[^%]*?%}/g;
17
+
18
+ let match;
19
+ while ((match = tagImgRegex.exec(content)) !== null) {
20
+ urls.push(match[1]);
21
+ }
22
+
23
+ return urls;
24
+ }
25
+
26
+
27
+ // 远程图片尺寸探测
28
+ async function getImageRatio(ctx, url) {
29
+ if (!url.startsWith('http')) {
30
+ return null;
31
+ }
32
+ try {
33
+ const result = await probe(url);
34
+ return `${result.width}/${result.height}`;
35
+ } catch (e) {
36
+ ctx.log.warn(`❌ 获取失败: ${url}`, e.message);
37
+ return null;
38
+ }
39
+ }
40
+
41
+
42
+ // 主逻辑
43
+ module.exports = async (ctx, options) => {
44
+ const cacheExists = fs.existsSync(outputPath);
45
+ if (cacheExists) {
46
+ ctx.log.info('正在获取图片长宽比。缓存已存在,开始增量更新...');
47
+ } else {
48
+ ctx.log.info('正在获取图片长宽比。首次可能耗时较久,请耐心等待...');
49
+ }
50
+
51
+ const mdFiles = glob.sync('source/**/*.md');
52
+
53
+ for (const file of mdFiles) {
54
+ const relative = path.relative(process.cwd(), file);
55
+ const content = fs.readFileSync(file, 'utf8');
56
+ const imageUrls = extractImageUrls(content);
57
+ const currentUrls = new Set(imageUrls);
58
+
59
+ // 初始化或清理旧数据
60
+ if (!cache[relative]) {
61
+ cache[relative] = {};
62
+ } else {
63
+ for (const oldUrl of Object.keys(cache[relative])) {
64
+ if (!currentUrls.has(oldUrl)) {
65
+ delete cache[relative][oldUrl];
66
+ }
67
+ }
68
+ }
69
+
70
+ // 探测新图片
71
+ for (const url of imageUrls) {
72
+ if (cache[relative][url]) {
73
+ continue;
74
+ }
75
+ const ratio = await getImageRatio(ctx, url);
76
+ if (ratio) {
77
+ cache[relative][url] = ratio;
78
+ ctx.log.info(`已添加: ${url} → ${ratio}`);
79
+
80
+ // 🧠 实时写入(增量更新,支持中断恢复)
81
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
82
+ fs.writeFileSync(outputPath, JSON.stringify(cache, null, 2));
83
+ }
84
+ }
85
+ }
86
+
87
+ ctx.log.info('[image-ratios.json] 生成完成');
88
+ };