hexo-theme-stellar 1.32.1 → 1.32.3

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 (110) hide show
  1. package/README.md +22 -4
  2. package/_config.yml +55 -41
  3. package/layout/_partial/comments/artalk/layout.ejs +1 -1
  4. package/layout/_partial/comments/artalk/script.ejs +22 -1
  5. package/layout/_partial/cover/post_cover.ejs +1 -5
  6. package/layout/_partial/cover/wiki_cover.ejs +1 -1
  7. package/layout/_partial/main/footer.ejs +15 -5
  8. package/layout/_partial/main/navbar/article_banner.ejs +3 -3
  9. package/layout/_partial/main/navbar/ghinfo.ejs +1 -1
  10. package/layout/_partial/scripts/defines.ejs +3 -1
  11. package/layout/_partial/scripts/lazyload.ejs +67 -0
  12. package/layout/_partial/scripts/utils.ejs +1 -0
  13. package/layout/_partial/scripts.ejs +1 -0
  14. package/layout/_partial/sidebar/index_leftbar.ejs +1 -1
  15. package/layout/_partial/sidebar/logo.ejs +1 -1
  16. package/layout/_partial/widgets/author.ejs +1 -1
  17. package/layout/_partial/widgets/ghissues.ejs +1 -1
  18. package/layout/_partial/widgets/ghrepo.ejs +2 -2
  19. package/layout/_partial/widgets/ghuser.ejs +2 -2
  20. package/layout/_partial/widgets/markdown.ejs +1 -1
  21. package/layout/_partial/widgets/recent.ejs +1 -1
  22. package/layout/_partial/widgets/related.ejs +1 -1
  23. package/layout/_partial/widgets/timeline.ejs +1 -1
  24. package/layout/_partial/widgets/tree.ejs +1 -1
  25. package/layout/_plugins/fancybox.ejs +7 -3
  26. package/layout/_plugins/scrollreveal.ejs +3 -3
  27. package/package.json +1 -1
  28. package/scripts/tags/lib/albums.js +4 -3
  29. package/scripts/tags/lib/banner.js +1 -1
  30. package/scripts/tags/lib/chat.js +1 -5
  31. package/scripts/tags/lib/friends.js +5 -2
  32. package/scripts/tags/lib/gallery.js +4 -3
  33. package/scripts/tags/lib/image.js +5 -5
  34. package/scripts/tags/lib/link.js +1 -5
  35. package/scripts/tags/lib/md.js +1 -1
  36. package/scripts/tags/lib/posters.js +5 -4
  37. package/scripts/tags/lib/sites.js +9 -3
  38. package/scripts/tags/lib/timeline.js +1 -1
  39. package/source/css/_common/base.styl +2 -5
  40. package/source/css/_common/blockquote.styl +1 -1
  41. package/source/css/_common/blur.styl +7 -7
  42. package/source/css/_common/button.styl +2 -2
  43. package/source/css/_common/cap.styl +1 -1
  44. package/source/css/_common/device.styl +4 -4
  45. package/source/css/_common/highlight.styl +2 -0
  46. package/source/css/_common/html.styl +1 -1
  47. package/source/css/_common/svg.styl +1 -1
  48. package/source/css/_common/title.styl +1 -1
  49. package/source/css/_components/layout.styl +2 -2
  50. package/source/css/_components/list.styl +1 -2
  51. package/source/css/_components/main.styl +8 -4
  52. package/source/css/_components/md.styl +2 -2
  53. package/source/css/_components/pages/archives.styl +5 -5
  54. package/source/css/_components/pages/article-story.styl +11 -11
  55. package/source/css/_components/pages/article-tech.styl +2 -2
  56. package/source/css/_components/pages/notebook.styl +2 -2
  57. package/source/css/_components/partial/footer.styl +5 -9
  58. package/source/css/_components/partial/navbar.styl +2 -2
  59. package/source/css/_components/partial/related.styl +6 -6
  60. package/source/css/_components/sidebar/footer.styl +1 -1
  61. package/source/css/_components/sidebar/menu.styl +3 -3
  62. package/source/css/_components/sidebar/search.styl +7 -7
  63. package/source/css/_components/sidebar/sidebar.styl +24 -24
  64. package/source/css/_components/tag-plugins/button.styl +2 -2
  65. package/source/css/_components/tag-plugins/chat.styl +44 -8
  66. package/source/css/_components/tag-plugins/checkbox.styl +1 -1
  67. package/source/css/_components/tag-plugins/copy.styl +4 -3
  68. package/source/css/_components/tag-plugins/friends.styl +5 -6
  69. package/source/css/_components/tag-plugins/friends_posts.styl +8 -7
  70. package/source/css/_components/tag-plugins/gallery.styl +1 -2
  71. package/source/css/_components/tag-plugins/image.styl +1 -1
  72. package/source/css/_components/tag-plugins/inline-labels.styl +3 -3
  73. package/source/css/_components/tag-plugins/okr.styl +2 -3
  74. package/source/css/_components/tag-plugins/poetry.styl +1 -1
  75. package/source/css/_components/tag-plugins/quot.styl +2 -25
  76. package/source/css/_components/tag-plugins/read/paper.styl +2 -2
  77. package/source/css/_components/tag-plugins/read/reel.styl +4 -4
  78. package/source/css/_components/tag-plugins/sites.styl +14 -11
  79. package/source/css/_components/tag-plugins/tabs.styl +1 -1
  80. package/source/css/_components/tag-plugins/timeline.styl +10 -4
  81. package/source/css/_components/widgets/components.styl +3 -3
  82. package/source/css/_components/widgets/ghuser.styl +3 -3
  83. package/source/css/_components/widgets/list.styl +1 -1
  84. package/source/css/_components/widgets/markdown.styl +9 -3
  85. package/source/css/_components/widgets/related.styl +3 -3
  86. package/source/css/_components/widgets/tagcloud.styl +2 -2
  87. package/source/css/_components/widgets/timeline.styl +2 -2
  88. package/source/css/_components/widgets/toc.styl +7 -3
  89. package/source/css/_components/widgets/widgets.styl +4 -4
  90. package/source/css/_custom.styl +26 -38
  91. package/source/css/_defines/const.styl +1 -5
  92. package/source/css/_defines/func.styl +4 -4
  93. package/source/css/_defines/theme_base.styl +105 -0
  94. package/source/css/_defines/theme_colorful.styl +117 -0
  95. package/source/css/_plugins/comments/artalk.styl +28 -8
  96. package/source/css/_plugins/comments/twikoo.styl +10 -10
  97. package/source/css/_plugins/comments/waline.styl +2 -2
  98. package/source/css/_plugins/index.styl +1 -2
  99. package/source/css/_plugins/lazyload.styl +40 -50
  100. package/source/css/_plugins/mermaid.styl +1 -1
  101. package/source/css/_plugins/swiper.styl +2 -2
  102. package/source/css/_plugins/tianli_gpt.styl +8 -8
  103. package/source/css/main.styl +2 -1
  104. package/source/js/services/friends.js +1 -0
  105. package/source/js/services/friends_and_posts.js +1 -0
  106. package/source/js/services/sites.js +1 -0
  107. package/source/js/services/timeline.js +1 -0
  108. package/layout/_plugins/lazyload.ejs +0 -21
  109. package/source/css/_components/tag-plugins/common.styl +0 -120
  110. package/source/css/_defines/theme.styl +0 -120
package/README.md CHANGED
@@ -1,6 +1,24 @@
1
1
  # Stellar - 每个人的独立博客
2
2
 
3
- Stellar 是一个内置文档系统的简约商务风 Hexo 主题,支持丰富的标签和动态数据组件,请配合 [文档](https://xaoxuu.com/wiki/stellar/) 使用。
3
+ Stellar 是一个极为强大的综合型 Hexo 主题,包含博客系统、知识库系统、专栏系统、笔记系统,内置海量的标签和动态数据组件。
4
+
5
+ ## 亮点
6
+
7
+ - 支持技术/生活文章布局风格,为不同类型的文章使用不同的风格。
8
+ - 内置 wiki 系统,可以展示多个项目文档,或个人知识库。
9
+ - 内置专栏系统,可以沉浸式阅读专栏系列文章。
10
+ - 内置笔记系统,更方便梳理笔记。
11
+ - 内置海量的灵活而强大的标签组件,互相之间还可以混搭嵌套。
12
+ - 内置多种动态数据组件,静态博客更新不再依赖于重新部署。
13
+ - 动态时间线(像发朋友圈一样发布短文,也可以订阅他人的时间线)
14
+ - 自动化的动态友链(自动检测友链状态、打标签、友链文章订阅)
15
+ - 渲染远程 markdown 文件(例如渲染项目仓库的 README 以减少重复工作)
16
+ - 模块化设计,内置多种复用性极强的小组件,自由搭配布局。
17
+ - 图片懒加载占位固定原图长宽比,不会发生高度跳变,体验更佳。
18
+ - 支持一站多作者,可以为不同文章指定不同的作者,每位作者都有专属主页。
19
+ - 社区文化:可订阅「探索号」时间线数据源获取社区用户的宝贵经验分享。
20
+
21
+ 上述亮点都可以在 [文档](https://xaoxuu.com/wiki/stellar/) 中找到详细使用方法。
4
22
 
5
23
  [![Stargazers over time](https://starchart.cc/xaoxuu/hexo-theme-stellar.svg)](https://starchart.cc/xaoxuu/hexo-theme-stellar)
6
24
 
@@ -10,10 +28,10 @@ Stellar 是一个内置文档系统的简约商务风 Hexo 主题,支持丰富
10
28
  Check your environment:
11
29
 
12
30
  ```yaml
13
- Hexo: 6.3.0 ~ 7.0.0
31
+ Hexo: 6.3.0 ~ latest
14
32
  hexo-cli: 4.3.0 ~ latest
15
- node: 14.17.3 ~ 20.10.0 # 建议选择 LTS 版本,过高的版本 hexo 还没有进行兼容。
16
- npm: 6.14.13 ~ 10.2.3
33
+ node: 14.17.3 ~ latest LTS # 建议选择 LTS 版本,过高的版本 hexo 还没有进行兼容。
34
+ npm: 6.14.13 ~ latest
17
35
  ```
18
36
 
19
37
  Edit your `_config.yml`:
package/_config.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  ######## Stellar info ########
2
2
  stellar:
3
- version: '1.32.1'
3
+ version: '1.32.3'
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
@@ -315,7 +315,15 @@ comments:
315
315
  js: https://unpkg.com/artalk@2.9/dist/Artalk.js
316
316
  server: # 后端服务地址
317
317
  site: '' # 站点名称
318
- darkMode: auto
318
+ darkMode: auto # 其它模式都有问题,慎用,否则后果自负
319
+ fancybox: true # 是否为评论区启用 fancybox
320
+ # artalk 有三类图片:1.上传至服务端 2.上传至服务端后利用upgit上传至图床 3.前端上传至图床(本配置为此类)
321
+ # 配置此项时将覆盖服务端上传能力
322
+ imageUploader:
323
+ # 以兰空图床为例,下列填写内容为:
324
+ # api: 'https://xxxxxx/api/v1/upload' # 图床上传地址
325
+ # token: 'Bearer xxxxxxxxxxxxxx' # 图床验证
326
+ # resp: 'data.links.url' # 图片地址返回值的字段
319
327
 
320
328
 
321
329
  ######## Footer ########
@@ -334,19 +342,30 @@ footer:
334
342
  # icon: '<img src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/social/942ebbf1a4b91.svg"/>'
335
343
  # url: /about/#comments
336
344
  sitemap:
337
- # '博客':
338
- # - '[近期](/)'
339
- # - '[分类](/)'
340
- # - '[标签](/)'
341
- # - '[归档](/)'
342
- # '项目':
343
- # - '[开源库](/)'
344
- # '社交':
345
- # - '[友链](/)'
346
- # - '[留言板](/)'
347
- # '更多':
348
- # - '[关于本站](/)'
349
- # - '[GitHub](/)'
345
+ # - title: 博客
346
+ # items:
347
+ # - '[近期发布](/)'
348
+ # - '[分类](/blog/categories/)'
349
+ # - '[标签](/blog/tags/)'
350
+ # - '[归档](/blog/archives/)'
351
+ # - title: 项目
352
+ # items:
353
+ # - '[xxx](/)'
354
+ # - '[xxx](/)'
355
+ # - '[xxx](/)'
356
+ # - '[xxx](/)'
357
+ # - title: 社交
358
+ # items:
359
+ # - '[xxx](/)'
360
+ # - '[xxx](/)'
361
+ # - '[xxx](/)'
362
+ # - '[xxx](/)'
363
+ # - title: 关于
364
+ # items:
365
+ # - '[xxx](/)'
366
+ # - '[xxx](/)'
367
+ # - '[xxx](/)'
368
+ # - '[xxx](/)'
350
369
  content: | # 支持 Markdown 格式
351
370
  本站由 [{author.name}](/) 使用 [{theme.name} {theme.version}]({theme.tree}) 主题创建。
352
371
  本博客所有文章除特别声明外,均采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 许可协议,转载请注明出处。
@@ -434,7 +453,10 @@ tag_plugins:
434
453
  dependencies:
435
454
  jquery: https://gcore.jsdelivr.net/npm/jquery@3.7/dist/jquery.min.js
436
455
  marked: https://gcore.jsdelivr.net/npm/marked@13.0/lib/marked.umd.min.js
437
-
456
+ lazyload:
457
+ js: https://gcore.jsdelivr.net/npm/vanilla-lazyload@19.1/dist/lazyload.min.js
458
+ transition: fade # blur, fade
459
+ fix_ratio: true # true / false
438
460
 
439
461
  # 内置服务,按需加载(页面内用到了就会加载,没有用到就不会加载)
440
462
  data_services:
@@ -498,17 +520,6 @@ plugins:
498
520
  service: flying_pages # flying_pages
499
521
  flying_pages: https://gcore.jsdelivr.net/npm/flying-pages@2/flying-pages.min.js
500
522
 
501
- # lazyload
502
- # https://www.npmjs.com/package/vanilla-lazyload
503
- lazyload:
504
- enable: true # [hexo clean && hexo s] is required after changing this value.
505
- js: https://gcore.jsdelivr.net/npm/vanilla-lazyload@19.1/dist/lazyload.min.js
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
-
512
523
  # https://fancyapps.com/docs/ui/fancybox/
513
524
  # available for {% image xxx %}
514
525
  fancybox:
@@ -530,11 +541,11 @@ plugins:
530
541
 
531
542
  # https://scrollrevealjs.org/api/reveal.html
532
543
  scrollreveal:
533
- enable: #true
544
+ enable: #true # 慎用,有些时候打开页面空白
534
545
  js: https://gcore.jsdelivr.net/npm/scrollreveal@4.0/dist/scrollreveal.min.js
535
- distance: 16px
536
- duration: 800 # ms
537
- interval: 100 # ms
546
+ distance: 8px
547
+ duration: 500 # ms
548
+ interval: 50 # ms
538
549
  scale: 1 # 0.1~1
539
550
 
540
551
  # AI 摘要
@@ -615,10 +626,9 @@ style:
615
626
  code: 85% # 相较于其所在行的文本大小,建议用百分比
616
627
  codeblock: 0.8125rem # 13px
617
628
  font-family:
618
- logo: 'system-ui, "Microsoft Yahei", "Segoe UI", -apple-system, Roboto, Ubuntu, "Helvetica Neue", Arial, "WenQuanYi Micro Hei", sans-serif'
619
- body: 'system-ui, "Microsoft Yahei", "Segoe UI", -apple-system, Roboto, Ubuntu, "Helvetica Neue", Arial, "WenQuanYi Micro Hei", sans-serif'
620
- code: 'Menlo, Monaco, Consolas, system-ui, "Courier New", monospace, sans-serif'
621
- codeblock: 'Menlo, Monaco, Consolas, system-ui, "Courier New", monospace, sans-serif'
629
+ body: 'system-ui, "Microsoft Yahei", "Segoe UI", Arial, sans-serif'
630
+ code: 'Menlo, Monaco, Consolas, system-ui, monospace, sans-serif'
631
+ codeblock: 'Menlo, Monaco, Consolas, system-ui, monospace, sans-serif'
622
632
  text-align: left
623
633
  prefix:
624
634
  h2: https://api.iconify.design/ci:heading-h2.svg
@@ -654,18 +664,20 @@ style:
654
664
  start: 'linear-gradient(to right, hsl(215, 95%, 64%), hsl(195, 95%, 60%), hsl(165, 95%, 56%), hsl(165, 95%, 56%), hsl(195 95% 60%), hsl(215, 95%, 64%))'
655
665
  leftbar:
656
666
  # 可以设置:纯色/渐变色/图片作为背景
657
- # background: var(--leftbar-bg)
667
+ background-color: var(--card) # var(--block)
658
668
  background-image: url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.13/image/sidebar-bg1@small.jpg)
659
669
  blur-px: 100px
660
- blur-bg: var(--alpha60)
670
+ blur-bg: var(--bg-a60)
671
+ background-opacity: 0.8
661
672
  paginator:
662
673
  prev: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/arrow/f049bbd4e88ec.svg
663
674
  next: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/arrow/064b95430caf4.svg
664
675
  error_page: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/404/1c830bfcd517d.svg
665
- site:
666
- background-image: #'url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.14/image/site-bg1@small.webp)' # 未完全适配,慎用
676
+ site: # 使用 background-image 后,blur 设置才有效
677
+ # background-image: url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.14/image/site-bg1@small.webp)
667
678
  blur-px: 100px
668
- blur-bg: var(--alpha75)
679
+ blur-bg: var(--bg-a75)
680
+ blur-sat: 300%
669
681
  # 技术文章内页各级标题前面的符号
670
682
  header_prefix:
671
683
  h2: '⌘'
@@ -682,7 +694,9 @@ default:
682
694
  project: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/image/2779789.png
683
695
  banner: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/banner/books.jpg
684
696
  topic: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/image/10433048.png
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"
697
+ loading: https://api.iconify.design/eos-icons:three-dots-loading.svg?color=%231cd0fd
698
+ # loading: https://github.githubassets.com/images/mona-loading-dark.gif
699
+ image_onerror: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2rem' height='2rem' 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"
686
700
 
687
701
  api_host:
688
702
  ghapi: api.github.com
@@ -1,7 +1,7 @@
1
1
  <%
2
2
  function layoutDiv() {
3
3
  var el = '';
4
- el += '<div id="artalk_container"';
4
+ el += `<div class="artalk ${theme.comments.artalk?.fancybox ? 'with-fancybox' : ''}" id="artalk_container"`;
5
5
  let cfg = {};
6
6
  if (page.comment_id) {
7
7
  cfg['comment_id'] = page.comment_id;
@@ -6,6 +6,10 @@
6
6
  if (!el) return;
7
7
  utils.css('<%- theme.comments.artalk.css %>');
8
8
  utils.js('<%- theme.comments.artalk.js %>', {defer: true}).then(function () {
9
+ // 监听 Artalk 事件
10
+ Artalk.use((ctx) => {
11
+ ctx.on('list-loaded', () => window.lazyLoadInstance?.update())
12
+ })
9
13
  const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
10
14
  const artalk = Artalk.init({
11
15
  el: '#artalk_container',
@@ -13,7 +17,24 @@
13
17
  pageTitle: '<%= page.title %>',
14
18
  server: '<%= theme.comments.artalk.server %>',
15
19
  site: '<%= theme.comments.artalk.site %>',
16
- darkMode: '<%= theme.comments.artalk.darkMode %>'
20
+ darkMode: '<%= theme.comments.artalk.darkMode %>',
21
+ <% if (theme.comments.artalk.imageUploader?.api) { %>
22
+ imgUploader: function(file) {
23
+ let headers = new Headers();
24
+ headers.set('Accept', 'application/json');
25
+ <% if (theme.comments.artalk.imageUploader?.token) { %>
26
+ headers.set('Authorization', '<%= theme.comments.artalk.imageUploader?.token %>')
27
+ <% } %>
28
+ let formData = new FormData();
29
+ formData.append('file', file);
30
+ return fetch('<%= theme.comments.artalk.imageUploader?.api %>',{
31
+ method: 'POST',
32
+ body: formData,
33
+ headers: headers
34
+ }).then((resp) => resp.json())
35
+ .then((resp) => resp.<%= theme.comments.artalk.imageUploader?.resp %>)
36
+ },
37
+ <% } %>
17
38
  });
18
39
  });
19
40
  }
@@ -28,11 +28,7 @@ function div() {
28
28
  }
29
29
  el += '<div class="l_cover post' + scrollreveal(' ') + '">';
30
30
  el += '<div class="cover">';
31
- if (theme.plugins.lazyload && theme.plugins.lazyload.enable) {
32
- el += '<div class="lazy img bg" data-bg="' + url + '"></div>';
33
- } else {
34
- el += '<div class="lazy img bg" style="background-image:url(&quot;' + url + '&quot;)"></div>';
35
- }
31
+ el += '<div class="lazy img bg" data-bg="' + url + '"></div>';
36
32
  el += '</div>';
37
33
  el += '</div>';
38
34
  return el;
@@ -18,7 +18,7 @@ function layoutWikiCover() {
18
18
  if (coverpage === true) {
19
19
  coverpage = ['cover', 'title', 'description'];
20
20
  }
21
- el += '<div class="l_cover wiki' + scrollreveal(' ') + '">';
21
+ el += '<div class="l_cover wiki">';
22
22
  el += '<article class="cover-wrap md-text">';
23
23
 
24
24
  if (cover?.length > 0 && coverpage.includes('cover')) {
@@ -5,15 +5,25 @@ function layoutDiv() {
5
5
  el += `<footer class="page-footer${scrollreveal(' ')} footnote">`
6
6
  el += '<hr>'
7
7
  // sitemap
8
- if (theme.footer.sitemap && Object.keys(theme.footer.sitemap).length > 0) {
9
- el += '<div class="sitemap">'
10
- for (let group of Object.keys(theme.footer.sitemap)) {
11
- let items = theme.footer.sitemap[group]
8
+ const sitemap = theme.footer.sitemap
9
+ if (sitemap?.length > 0) {
10
+ var count = sitemap.length
11
+ if ([6].includes(count)) {
12
+ count = 3
13
+ } else if ([7,8].includes(count)) {
14
+ count = 4
15
+ } else {
16
+ count = Math.min(sitemap.length, 5)
17
+ }
18
+ el += `<div class="sitemap" style="column-count:${count};">`
19
+ for (let group of sitemap) {
20
+ let title = group.title
21
+ let items = group.items
12
22
  if (items == undefined || items.length == 0) {
13
23
  continue
14
24
  }
15
25
  el += '<div class="sitemap-group">'
16
- el += '<span class="fs15">' + group + '</span>'
26
+ el += '<span class="fs15">' + title + '</span>'
17
27
  items.forEach((item, i) => {
18
28
  el += '<a href="' + url_for(md_link(item)) + '">'
19
29
  el += __(md_text(item))
@@ -70,7 +70,7 @@ function layoutSubtitle() {
70
70
 
71
71
  function layoutIcon() {
72
72
  if (banner.avatar?.length > 0 || banner.icon?.length > 0) {
73
- return `<img class="avatar" src="${banner.avatar || banner.icon}">`
73
+ return `<img class="lazy avatar" data-src="${banner.avatar || banner.icon}">`
74
74
  } else {
75
75
  return ''
76
76
  }
@@ -107,9 +107,9 @@ function layoutDiv() {
107
107
  const top = layoutBreadcrumb()
108
108
  var style = ``
109
109
  var el = ``
110
- el += `<div class="article banner top">`
110
+ el += `<div class="article banner${scrollreveal(' ')} top">`
111
111
  if (banner.url?.length > 0) {
112
- el += `<img class="bg" src="${banner.url}">`
112
+ el += `<img class="lazy bg" data-src="${banner.url}">`
113
113
  if (banner.color) {
114
114
  style += ' style="--text-banner:' + banner.color + '"'
115
115
  }
@@ -5,7 +5,7 @@ function layoutDiv() {
5
5
  return ''
6
6
  }
7
7
  return `
8
- <div class="right ghrepo ds-ghinfo" api="https://${theme.api_host.ghapi}/repos/${repo}">
8
+ <div class="right ghrepo data-service data-service 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>
@@ -33,10 +33,12 @@
33
33
  const def = {
34
34
  avatar: `<%- theme.default.avatar %>`,
35
35
  cover: `<%- theme.default.cover %>`,
36
+ loading: `<%- theme.default.loading %>`,
36
37
  };
37
38
  const deps = {
38
39
  jquery: `<%- url_for(theme.dependencies.jquery) %>`,
39
- marked: `<%- url_for(theme.dependencies.marked) %>`
40
+ marked: `<%- url_for(theme.dependencies.marked) %>`,
41
+ lazyload: `<%- url_for(theme.dependencies.lazyload) %>`
40
42
  }
41
43
 
42
44
 
@@ -0,0 +1,67 @@
1
+ <script async src="<%- url_for(theme.dependencies.lazyload.js) %>"></script>
2
+ <script>
3
+ // https://www.npmjs.com/package/vanilla-lazyload
4
+ // Set the options globally
5
+ // to make LazyLoad self-initialize
6
+ window.lazyLoadOptions = {
7
+ elements_selector: ".lazy, .lazyload",
8
+ callback_loaded: (el) => {
9
+ el.classList.add('loaded');
10
+ const wrapper = el.closest('.lazy-box');
11
+ const icon = wrapper?.querySelector('.lazy-icon');
12
+ if (icon) icon.remove();
13
+ }
14
+ };
15
+ // Listen to the initialization event
16
+ // and get the instance of LazyLoad
17
+ window.addEventListener(
18
+ "LazyLoad::Initialized",
19
+ function (event) {
20
+ window.lazyLoadInstance = event.detail.instance;
21
+ },
22
+ false
23
+ );
24
+ document.addEventListener('DOMContentLoaded', function () {
25
+ window.lazyLoadInstance?.update();
26
+ });
27
+
28
+ window.wrapLazyloadImages = (container) => {
29
+ if (typeof container === 'string') {
30
+ container = document.querySelector(container);
31
+ }
32
+ if (!container) return;
33
+
34
+ const images = container.querySelectorAll('img');
35
+ images.forEach((img) => {
36
+ if (img.classList.contains('lazy')) return;
37
+
38
+ const src = img.getAttribute('src');
39
+ if (!src) return;
40
+
41
+ const wrapper = document.createElement('div');
42
+ wrapper.className = 'lazy-box';
43
+
44
+ const newImg = img.cloneNode();
45
+ newImg.removeAttribute('src');
46
+ newImg.setAttribute('data-src', src);
47
+ newImg.classList.add('lazy');
48
+
49
+ const icon = document.createElement('div');
50
+ icon.className = 'lazy-icon';
51
+ if (def.loading) {
52
+ icon.style.backgroundImage = `url("${def.loading}")`;
53
+ }
54
+
55
+ wrapper.appendChild(newImg);
56
+ wrapper.appendChild(icon);
57
+
58
+ img.replaceWith(wrapper);
59
+ });
60
+
61
+ // 通知 LazyLoad 更新
62
+ if (window.lazyLoadInstance?.update) {
63
+ window.lazyLoadInstance.update();
64
+ }
65
+ }
66
+
67
+ </script>
@@ -1,4 +1,5 @@
1
1
  <script type="text/javascript">
2
+
2
3
  function RunItem() {
3
4
  this.list = []; // 存放回调函数
4
5
  this.start = () => {
@@ -19,6 +19,7 @@ function custom_inject() {
19
19
  <%- partial('scripts/utils') %>
20
20
  <%- partial('scripts/sidebar') %>
21
21
  <%- partial('scripts/tagtree') %>
22
+ <%- partial('scripts/lazyload') %>
22
23
 
23
24
  <!-- required -->
24
25
  <script src="<%- url_for(`${theme.stellar.main_js}?v=${stellar_info('version')}`) %>" defer></script>
@@ -62,7 +62,7 @@ if (typeof page.leftbar == 'string') {
62
62
  function layoutTitle(main, url, sub) {
63
63
  var el = '';
64
64
  el += '<a class="title" href="' + url_for(url || "/") + '">';
65
- el += '<div class="main" ff="title">' + main + '</div>';
65
+ el += '<div class="main">' + main + '</div>';
66
66
  if (sub) {
67
67
  let arr = sub.split('|');
68
68
  if (arr.length > 1) {
@@ -23,7 +23,7 @@ if (page.logo) {
23
23
  function layoutTitle(main, url, sub) {
24
24
  var el = ''
25
25
  el += `<a class="title" href="${url_for(url || "/")}">`
26
- el += `<div class="main" ff="title">${main}</div>`
26
+ el += `<div class="main">${main}</div>`
27
27
  if (sub) {
28
28
  const arr = sub.split('|')
29
29
  if (arr.length > 1) {
@@ -21,7 +21,7 @@ function layoutDiv() {
21
21
  el += `<div class="avatar"><img type="img" id="avatar_url" src="${author.avatar}"></div>`
22
22
  }
23
23
  // username
24
- el += `<p class="username" ff="title" type="text" id="name">${author.name}</p>`
24
+ el += `<p class="username" type="text" id="name">${author.name}</p>`
25
25
  el += `<p class="bio" type="text" id="bio">${author.desc || author.description}</p>`
26
26
 
27
27
  // homepage
@@ -26,7 +26,7 @@ function layoutDiv() {
26
26
  el += '</div>';
27
27
  }
28
28
  el += '<div class="widget-body fs14">';
29
- el += '<div class="tag-plugin timeline ds-timeline"';
29
+ el += '<div class="tag-plugin timeline data-service ds-timeline"';
30
30
  ['api', 'user'].forEach(key => {
31
31
  if (item[key]) {
32
32
  el += ' ' + key + '="' + item[key] + '"';
@@ -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="https://' + theme.api_host.ghapi + '/repos/' + repo + '">';
22
+ el += '<div class="items data-service 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="https://' + theme.api_host.ghapi + '/repos/' + repo + '/tags">';
38
+ el += '<div class="flex-row data-service 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,12 +24,12 @@ 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="https://' + theme.api_host.ghapi + '/users/' + item.username + '">';
27
+ el += '<div class="widget-body data-service 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
  }
31
31
  // username
32
- el += '<p class="username" ff="title" type="text" id="name">&nbsp;</p>';
32
+ el += '<p class="username" type="text" id="name">&nbsp;</p>';
33
33
  el += '<p class="bio" type="text" id="bio">&nbsp;</p>';
34
34
 
35
35
  el += '<div class="buttons">';
@@ -13,7 +13,7 @@ function layoutDiv() {
13
13
  el += markdown(item.content);
14
14
  }
15
15
  if (item.src) {
16
- el += `<div class="ds-mdrender" src="${item.src}"></div>`
16
+ el += `<div class="data-service ds-mdrender" src="${item.src}"></div>`
17
17
  }
18
18
  if (item.linklist) {
19
19
  el += partial('components/linklist', {item: item.linklist})
@@ -1,6 +1,6 @@
1
1
  <%
2
2
  function layoutDiv() {
3
- var el = `<widget class="widget-wrapper${scrollreveal(' ')} post-list">`
3
+ var el = `<widget class="widget-wrapper${scrollreveal(' ')} recent post-list">`
4
4
  // header
5
5
  el += '<div class="widget-header dis-select">';
6
6
  el += '<span class="name">' + __("meta.recent_update") + '</span>';
@@ -8,7 +8,7 @@ function relatedPostsInTopic() {
8
8
  return ''
9
9
  }
10
10
  var el = ''
11
- el += `<widget class="widget-wrapper${scrollreveal(' ')} post-list">`
11
+ el += `<widget class="widget-wrapper related post-list">`
12
12
  el += `<div class="widget-header dis-select">`
13
13
  el += `<span class="name">${__('btn.topic') + __('symbol.colon') + (topic.name || topic.title)}</span>`
14
14
  el += `</div>`
@@ -11,7 +11,7 @@ function layoutDiv() {
11
11
  el += '</div>';
12
12
  }
13
13
  el += '<div class="widget-body fs14">';
14
- el += `<div class="tag-plugin timeline ds-${(item.type || 'timeline')}"`;
14
+ el += `<div class="tag-plugin timeline data-service ds-${(item.type || 'timeline')}"`;
15
15
  ['api', 'user', 'hide', 'limit'].forEach(key => {
16
16
  if (item[key]) {
17
17
  el += ' ' + key + '="' + item[key] + '"';
@@ -60,7 +60,7 @@ function layoutDiv(fallback) {
60
60
  }
61
61
  }
62
62
  if (el.trim().length > 0) {
63
- return `<widget class="widget-wrapper${scrollreveal(' ')} post-list">${el}</widget>`
63
+ return `<widget class="widget-wrapper doc-tree post-list">${el}</widget>`
64
64
  } else {
65
65
  return ''
66
66
  }
@@ -4,14 +4,18 @@
4
4
  css: `<%- conf.css %>`,
5
5
  js: `<%- conf.js %>`
6
6
  };
7
- var selector = '[data-fancybox]:not(.error)';
7
+ var selector = '[data-fancybox]:not(.error), .with-fancybox .atk-content img:not([atk-emoticon])';
8
8
  if (ctx.fancybox.selector) {
9
9
  selector += `, ${ctx.fancybox.selector}`
10
10
  }
11
11
  var needFancybox = document.querySelectorAll(selector).length !== 0;
12
12
  if (!needFancybox) {
13
- const els = document.getElementsByClassName('ds-memos');
14
- if (els != undefined && els.length > 0) {
13
+ const memos = document.getElementsByClassName('ds-memos');
14
+ if (memos != undefined && memos.length > 0) {
15
+ needFancybox = true;
16
+ }
17
+ const fancybox = document.getElementsByClassName('with-fancybox');
18
+ if (fancybox != undefined && fancybox.length > 0) {
15
19
  needFancybox = true;
16
20
  }
17
21
  }
@@ -9,8 +9,8 @@
9
9
  opacity: 0,
10
10
  easing: "ease-out"
11
11
  };
12
- ScrollReveal().reveal('.l_left .slide-up', slideUp);
13
- ScrollReveal().reveal('.l_main .slide-up', slideUp);
14
- ScrollReveal().reveal('.l_right .slide-up', slideUp);
12
+ ScrollReveal({ container: '.widgets' }).reveal('.slide-up', { ...slideUp });
13
+ ScrollReveal({ container: '.l_main' }).reveal('.slide-up', { ...slideUp });
14
+ ScrollReveal({ container: '.l_right' }).reveal('.slide-up', { ...slideUp });
15
15
  });
16
16
  </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-stellar",
3
- "version": "1.32.1",
3
+ "version": "1.32.3",
4
4
  "description": "Elegant and powerful theme for Hexo.",
5
5
  "main": "package.json",
6
6
  "scripts": {
@@ -23,15 +23,16 @@ module.exports = ctx => function(args) {
23
23
  var el = ''
24
24
  el += `<div class="tag-plugin albums-wrap">`
25
25
  if (api) {
26
- el += `<div class="ds-friends" api="${api}"><div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}></div></div>`
26
+ el += `<div class="data-service ds-friends" api="${api}"><div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}></div></div>`
27
27
  } else if (args.group) {
28
28
  const links = ctx.theme.config.links || {}
29
29
  el += `<div class="tag-plugin gallery grid-box" layout="grid" ratio="square" ${ctx.args.joinTags(args, ['size']).join(' ')}>`
30
30
  for (let item of (links[args.group] || [])) {
31
31
  if (item?.url) {
32
32
  el += `<div class="grid-cell album-card">`
33
- el += `<a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="${item.url}">`
34
- el += `<img src="${item.cover || item.icon || item.avatar || ctx.theme.config.default.cover}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${ctx.theme.config.default.cover}&quot;;"/>`
33
+ el += `<a class="card-link lazy-box" target="_blank" rel="external nofollow noopener noreferrer" href="${item.url}">`
34
+ el += `<img class="lazy" data-src="${item.cover || item.icon || item.avatar || ctx.theme.config.default.cover}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${ctx.theme.config.default.cover}&quot;;"/>`
35
+ el += `<div class="lazy-icon" style="background-image:url(${ctx.theme.config.default.loading});"></div>`
35
36
  el += `<div class="image-meta">`
36
37
  if (item.title) {
37
38
  el += `<span class="image-caption">${item.title}</span>`