hexo-theme-stellar 1.31.0 → 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 (61) hide show
  1. package/_config.yml +14 -12
  2. package/_data/icons.yml +3 -3
  3. package/layout/_partial/comments/artalk/script.ejs +1 -2
  4. package/layout/_partial/comments/layout.ejs +1 -1
  5. package/layout/_partial/head.ejs +15 -3
  6. package/layout/_partial/scripts/theme.ejs +3 -3
  7. package/layout/_partial/sidebar/index_leftbar.ejs +9 -9
  8. package/layout/index.ejs +3 -1
  9. package/layout/layout.ejs +3 -2
  10. package/package.json +4 -2
  11. package/scripts/events/index.js +39 -2
  12. package/scripts/events/lib/fix_image_tags.js +44 -0
  13. package/scripts/events/lib/get_image_ratios.js +88 -0
  14. package/scripts/events/lib/version-check.js +2 -0
  15. package/scripts/helpers/json_ld.js +5 -1
  16. package/scripts/tags/lib/image.js +16 -6
  17. package/scripts/tags/lib/timeline.js +1 -1
  18. package/scripts/tags/lib/video.js +2 -2
  19. package/source/css/_common/base.styl +1 -2
  20. package/source/css/_common/canonical.styl +1 -1
  21. package/source/css/_common/highlight.styl +1 -1
  22. package/source/css/_components/layout.styl +11 -10
  23. package/source/css/_components/list.styl +3 -0
  24. package/source/css/_components/main.styl +1 -1
  25. package/source/css/_components/md.styl +4 -2
  26. package/source/css/_components/pages/archives.styl +2 -2
  27. package/source/css/_components/pages/article-story.styl +6 -0
  28. package/source/css/_components/pages/article-tech.styl +1 -1
  29. package/source/css/_components/pages/notebook.styl +1 -1
  30. package/source/css/_components/partial/article-banner.styl +4 -1
  31. package/source/css/_components/partial/footer.styl +1 -1
  32. package/source/css/_components/partial/navbar.styl +2 -1
  33. package/source/css/_components/sidebar/nav-area.styl +1 -1
  34. package/source/css/_components/sidebar/search.styl +44 -21
  35. package/source/css/_components/sidebar/sidebar.styl +9 -5
  36. package/source/css/_components/tag-plugins/banner.styl +1 -1
  37. package/source/css/_components/tag-plugins/button.styl +3 -4
  38. package/source/css/_components/tag-plugins/copy.styl +1 -1
  39. package/source/css/_components/tag-plugins/friends.styl +1 -1
  40. package/source/css/_components/tag-plugins/gallery.styl +6 -0
  41. package/source/css/_components/tag-plugins/image.styl +10 -0
  42. package/source/css/_components/tag-plugins/note.styl +1 -1
  43. package/source/css/_components/tag-plugins/override.styl +1 -1
  44. package/source/css/_components/tag-plugins/quot.styl +2 -2
  45. package/source/css/_components/tag-plugins/tabs.styl +4 -3
  46. package/source/css/_components/tag-plugins/timeline.styl +2 -2
  47. package/source/css/_components/tag-plugins/toc.styl +1 -1
  48. package/source/css/_components/widgets/markdown.styl +0 -7
  49. package/source/css/_components/widgets/toc.styl +6 -4
  50. package/source/css/_components/widgets/widgets.styl +0 -5
  51. package/source/css/_custom.styl +5 -7
  52. package/source/css/_defines/const.styl +1 -1
  53. package/source/css/_defines/func.styl +9 -5
  54. package/source/css/_defines/theme.styl +4 -15
  55. package/source/css/_plugins/comments/artalk.styl +114 -2
  56. package/source/css/_plugins/comments/twikoo.styl +3 -3
  57. package/source/css/_plugins/index.styl +5 -5
  58. package/source/css/_plugins/lazyload.styl +49 -2
  59. package/source/js/search/local-search.js +163 -151
  60. package/source/js/services/artalk_latest_comment.js +1 -1
  61. 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.31.0'
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
@@ -180,8 +180,6 @@ article:
180
180
  type: tech # tech: 默认技术类文章, story: 图文类文章,文字和段落间增距大
181
181
  # 缩进两个文字宽度,适合文字类博客,可以在 front-matter/topic/wiki 中覆盖此参数
182
182
  indent: # true / false
183
- # 如果没有指定封面,是否根据 tags 作为关键词搜索封面图片?
184
- auto_cover: false # search from https://source.unsplash.com/
185
183
  # 封面图宽高比
186
184
  cover_ratio: 2
187
185
  # 文章内横幅宽高比
@@ -222,6 +220,7 @@ comments:
222
220
  service: # beaudar, utterances, giscus, twikoo, waline, artalk
223
221
  comment_title: 快来参与讨论吧~
224
222
  lazyload: false # true / false
223
+ custom_css: # artalk,twikoo,... 可以为没有全局启用的评论加载自定义样式
225
224
  # beaudar
226
225
  # https://beaudar.lipk.org/
227
226
  beaudar:
@@ -312,10 +311,10 @@ comments:
312
311
  # Artalk
313
312
  # https://artalk.js.org/
314
313
  artalk:
315
- css: https://unpkg.com/artalk@2.8/dist/Artalk.css
316
- 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
317
316
  server: # 后端服务地址
318
- placeholder: ''
317
+ site: '' # 站点名称
319
318
  darkMode: auto
320
319
 
321
320
 
@@ -334,9 +333,6 @@ footer:
334
333
  # comments:
335
334
  # icon: '<img src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/social/942ebbf1a4b91.svg"/>'
336
335
  # url: /about/#comments
337
- # theme:
338
- # icon: default:theme
339
- # onclick: 'switchTheme()'
340
336
  sitemap:
341
337
  # '博客':
342
338
  # - '[近期](/)'
@@ -488,7 +484,7 @@ data_services:
488
484
 
489
485
 
490
486
  # 扩展插件接入方法:(插件名下面用 #plugin# 代替)
491
- # 1. 在这里增加 #plugin# 配置,至少赢含有 enable 字段,默认为空(不启用)
487
+ # 1. 在这里增加 #plugin# 配置,至少应含有 enable 字段,默认为空(不启用)
492
488
  # 2. 新建文件 layout/_plugins/#plugin#.ejs 文件中设置编写加载代码。
493
489
  # 2.1. 在该文件中可以直接使用 conf 来读取用户在【步骤 1】填写的配置字段内容
494
490
  # 2.2. 如果需要引入 css 或 js,可以使用 utils.css(xxx)、utils.js(xxx),具体可参考 layout/_plugins/fancybox.ejs
@@ -508,6 +504,10 @@ plugins:
508
504
  enable: true # [hexo clean && hexo s] is required after changing this value.
509
505
  js: https://gcore.jsdelivr.net/npm/vanilla-lazyload@19.1/dist/lazyload.min.js
510
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 # 图片宽度
511
511
 
512
512
  # https://fancyapps.com/docs/ui/fancybox/
513
513
  # available for {% image xxx %}
@@ -627,7 +627,9 @@ style:
627
627
  card: 16px # 文章内大部分卡片的圆角
628
628
  card-s: 12px # 文章内小型卡片的圆角
629
629
  bar: 8px # 横条类元素的圆角
630
- image: 12px # 图片圆角
630
+ image-l: 24px # 非技术类文章插图圆角
631
+ image: 16px # 技术类文章插图圆角
632
+ image-s: 8px # 评论区图片圆角(部分评论支持)
631
633
  color:
632
634
  # 动态颜色(会根据明暗主题重设明度值,只用关心色相和饱和度即可)
633
635
  background: 'hsl(212 16% 98%)' # 浅色背景颜色
@@ -680,7 +682,7 @@ default:
680
682
  project: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/image/2779789.png
681
683
  banner: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/banner/books.jpg
682
684
  topic: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/image/10433048.png
683
-
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"
684
686
 
685
687
  api_host:
686
688
  ghapi: api.github.com
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>
@@ -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]);
@@ -92,11 +92,25 @@ function custom_inject() {
92
92
  return el;
93
93
  }
94
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
+
95
108
  %>
96
109
 
97
110
  <head>
98
111
  <meta charset="utf-8">
99
112
  <meta name="hexo-theme" content="<%- stellar_info('tree') %>" theme-name="<%- stellar_info('name') %>" theme-version="<%- stellar_info('version') %>">
113
+ <%- generate_canonical() %>
100
114
  <%- generate_robots() %>
101
115
  <%- meta_generator() %>
102
116
  <meta http-equiv='x-dns-prefetch-control' content='on' />
@@ -109,9 +123,6 @@ function custom_inject() {
109
123
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
110
124
  <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#000">
111
125
  <meta name="theme-color" content="#f9fafb">
112
- <% if (theme.canonical.originalHost) { %>
113
- <link rel="canonical" href="https://<%= theme.canonical.originalHost + "/" + page.path %>">
114
- <% } %>
115
126
  <title><%- generate_title() %></title>
116
127
 
117
128
  <% if (theme.open_graph && theme.open_graph.enable) { %>
@@ -137,5 +148,6 @@ function custom_inject() {
137
148
  <%- css(theme.style.codeblock.highlightjs_theme) %>
138
149
  <% } %>
139
150
 
151
+ <%- json_ld() %>
140
152
  <%- custom_inject() %>
141
153
  </head>
@@ -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
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
@@ -65,7 +67,6 @@ if (theme.style.prefers_theme === 'auto') {
65
67
  html += partial('_partial/menubtn')
66
68
  html += `</div>`
67
69
  html += `<div class="scripts">`
68
- html += json_ld()
69
70
  html += partial('_partial/scripts')
70
71
  html += `</div>`
71
72
  html += `</body>`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-stellar",
3
- "version": "1.31.0",
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": {
@@ -20,12 +20,49 @@ hexo.on('generateAfter', () => {
20
20
  hexo.on('ready', () => {
21
21
  if (process.env.HEXO_READY === '1') return;
22
22
  process.env.HEXO_READY = '1';
23
+ const isClean = ['cl', 'clean'].some(arg => process.argv.includes(arg));
24
+ if (isClean) {
25
+ return;
26
+ }
23
27
  const { version, homepage, repository } = require('../../package.json');
28
+ console.log(``);
29
+
30
+ const line = '------------------------------------------------';
31
+ hexo.log.info(line);
24
32
  hexo.log.info(`Welcome to \x1b[33mStellar ${version}\x1b[0m
25
33
  \x1b[32mDOCS\x1b[0m ${homepage}
26
- \x1b[32mREPO\x1b[0m ${repository.url}
27
- `);
34
+ \x1b[32mREPO\x1b[0m ${repository.url}`);
35
+ hexo.log.info(line);
36
+ console.log(``);
28
37
  // version check
29
38
  const checkVersion = require('./lib/version-check');
30
39
  checkVersion(hexo, { useCache: true });
31
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
+ }
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
+ };
@@ -69,6 +69,7 @@ module.exports = (ctx, options = { useCache: true }) => {
69
69
  fetchLatestVersion((err, latest) => {
70
70
  if (err) return;
71
71
  if (localVersion !== latest) {
72
+ console.log(``);
72
73
  const line = '------------------------------------------------';
73
74
  ctx.log.warn(`\x1b[33m${line}\x1b[0m`);
74
75
  ctx.log.warn(``);
@@ -77,6 +78,7 @@ module.exports = (ctx, options = { useCache: true }) => {
77
78
  ctx.log.warn(` 请尽快升级: npm i ${packageName}@latest`);
78
79
  ctx.log.warn(``);
79
80
  ctx.log.warn(`\x1b[33m${line}\x1b[0m`);
81
+ console.log(``);
80
82
  }
81
83
  if (options.useCache) writeCache(latest);
82
84
  });
@@ -83,7 +83,11 @@ hexo.extend.helper.register('json_ld', function(args) {
83
83
  };
84
84
 
85
85
  if (config.keywords && config.keywords.length) {
86
- schema.keywords = config.keywords.join(', ');
86
+ if (Array.isArray(args)) {
87
+ schema.keywords = config.keywords.join(', ');
88
+ } else {
89
+ schema.keywords = config.keywords;
90
+ }
87
91
  }
88
92
  if (!this.is_home()) {
89
93
 
@@ -2,13 +2,13 @@
2
2
  * image.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/
3
3
  * 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来)
4
4
  *
5
- * {% image src [alt] [width:400px] [bg:#eee] [download:true/false/url] [fancybox:true/false/url] %}
5
+ * {% image src [alt] [width:400px] [bg:#eee] [download:true/false/url] [fancybox:true/false/url] [ratio] %}
6
6
  */
7
7
 
8
8
  'use strict'
9
9
 
10
10
  module.exports = ctx => function(args) {
11
- args = ctx.args.map(args, ['width', 'height', 'bg', 'download', 'padding', 'fancybox'], ['src', 'alt'])
11
+ args = ctx.args.map(args, ['width', 'height', 'bg', 'download', 'padding', 'fancybox', 'ratio'], ['src', 'alt'])
12
12
  var style = ''
13
13
  if (args.width) {
14
14
  style += 'width:' + args.width + ';'
@@ -39,7 +39,7 @@ module.exports = ctx => function(args) {
39
39
 
40
40
  function img(src, alt, style) {
41
41
  let img = ''
42
- img += '<img src="' + src + '"'
42
+ img += `<img src="${src}" data-src="${src}"`
43
43
  let a = '<a data-fancybox'
44
44
  if (alt) {
45
45
  img += ' alt="' + alt + '"'
@@ -48,9 +48,10 @@ module.exports = ctx => function(args) {
48
48
  if (fancybox && !fancyboxHref) {
49
49
  img += ` data-fancybox="${fancybox}"`
50
50
  }
51
- if (style.length > 0) {
51
+ if (style.length > 0 && !args.ratio) {
52
52
  img += ' style="' + style + '"'
53
53
  }
54
+ img += `onerror="this.src=&quot;${ctx.theme.config.default.image_onerror}&quot;"`
54
55
  img += '/>'
55
56
 
56
57
  if (fancyboxHref) {
@@ -65,8 +66,8 @@ module.exports = ctx => function(args) {
65
66
  // wrap
66
67
  el += '<div class="tag-plugin image">'
67
68
  // bg
68
- el += '<div class="image-bg"'
69
- if (args.bg || args.padding) {
69
+ el += `<div class="image-bg"`
70
+ if (args.bg || args.padding || args.ratio || style) {
70
71
  el += ' style="'
71
72
  if (args.bg && args.bg.length > 0) {
72
73
  el += 'background:' + args.bg + ';'
@@ -74,6 +75,15 @@ module.exports = ctx => function(args) {
74
75
  if (args.padding) {
75
76
  el += 'padding:' + args.padding + ';'
76
77
  }
78
+ if (args.ratio) {
79
+ el += 'aspect-ratio:' + args.ratio + ';'
80
+ if (style) {
81
+ el += style
82
+ }
83
+ } else if (style) {
84
+ // 如果设置了图片宽度,但没有长宽比,那背景区就要铺满宽度
85
+ el += 'width:100%;'
86
+ }
77
87
  el += '"'
78
88
  }
79
89
  el += '>'
@@ -18,7 +18,7 @@ function layoutNodeTitle(ctx, content) {
18
18
  var el = ''
19
19
  el += '<div class="header">'
20
20
  if (content && content.length > 0) {
21
- el += content
21
+ el += `<span>${content}</span>`
22
22
  }
23
23
  el += '</div>'
24
24
  return el
@@ -14,7 +14,7 @@ module.exports = ctx => function (args) {
14
14
  args.width = '100%'
15
15
  }
16
16
  if (args.bilibili) {
17
- return `<div class="tag-plugin video" style="aspect-ratio:${args.ratio || 16 / 9};max-width:${args.width};">
17
+ return `<div class="tag-plugin video-player" style="aspect-ratio:${args.ratio || 16 / 9};max-width:${args.width};">
18
18
  <iframe src="https://player.bilibili.com/player.html?bvid=${args.bilibili}&autoplay=${args.autoplay || 'false'}" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true">
19
19
  </iframe>
20
20
  </div>
@@ -26,7 +26,7 @@ module.exports = ctx => function (args) {
26
26
  } else {
27
27
  args.autoplay = '0'
28
28
  }
29
- return `<div class="tag-plugin video" style="aspect-ratio:${args.ratio || 16 / 9};max-width:${args.width};">
29
+ return `<div class="tag-plugin video-player" style="aspect-ratio:${args.ratio || 16 / 9};max-width:${args.width};">
30
30
  <iframe style="border:none" src="https://www.youtube.com/embed/${args.youtube}?rel=0&disablekb=1&playsinline=1&autoplay=${args.autoplay}" picture-in-picture="true" allowfullscreen="true" >
31
31
  </iframe>
32
32
  </div>
@@ -23,7 +23,6 @@ hr
23
23
  img
24
24
  max-width: 100%
25
25
 
26
-
27
26
  li
28
27
  font-size: 'calc(%s - 1px)' % var(--fsp)
29
28
 
@@ -46,7 +45,7 @@ table:not([class])
46
45
  background: var(--block)
47
46
  td,th
48
47
  padding: 0.5em 1em
49
- border: 1px solid var(--block-hover)
48
+ border: 1px solid var(--block-border)
50
49
  line-height: 1.5
51
50
  tr
52
51
  word-break: keep-all
@@ -5,7 +5,7 @@
5
5
  left: 50%
6
6
  transform: translateX(-50%)
7
7
  max-width: 90%
8
- background-color: var(--block-hover)
8
+ background-color: var(--block-border)
9
9
  color: var(--text-p1)
10
10
  font-size: 1rem
11
11
  font-family: #fff8e1
@@ -36,7 +36,7 @@ p>code:not([class]),li>code:not([class])
36
36
  display: block
37
37
  border-bottom-left-radius: $border-button
38
38
  border-bottom-right-radius: $border-button
39
- background: var(--block-hover)
39
+ background: var(--block-border)
40
40
  >table
41
41
  overflow: auto
42
42
  display: block