hexo-theme-stellar 1.42.1 → 1.43.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 (117) hide show
  1. package/.claude/skills/stellar-theme-dev/SKILL.md +1 -0
  2. package/CHANGELOG.md +31 -0
  3. package/THIRD-PARTY-NOTICES.md +28 -0
  4. package/_config.yml +17 -7
  5. package/_data/icons.yml +10 -9
  6. package/languages/en.yml +11 -0
  7. package/languages/zh-CN.yml +11 -0
  8. package/languages/zh-TW.yml +11 -0
  9. package/layout/_partial/comments/artalk/layout.ejs +1 -1
  10. package/layout/_partial/comments/beaudar/layout.ejs +1 -1
  11. package/layout/_partial/comments/giscus/layout.ejs +1 -1
  12. package/layout/_partial/comments/twikoo/layout.ejs +1 -1
  13. package/layout/_partial/comments/utterances/layout.ejs +1 -1
  14. package/layout/_partial/comments/waline/layout.ejs +1 -1
  15. package/layout/_partial/components/collection-item.ejs +44 -0
  16. package/layout/_partial/components/collection.ejs +26 -0
  17. package/layout/_partial/components/widget-frame.ejs +35 -0
  18. package/layout/_partial/cover/wiki_cover.ejs +82 -26
  19. package/layout/_partial/dropdown.ejs +62 -0
  20. package/layout/_partial/head.ejs +9 -0
  21. package/layout/_partial/main/navbar/breadcrumb/blog.ejs +1 -1
  22. package/layout/_partial/main/post_list/archive_item.ejs +12 -0
  23. package/layout/_partial/main/post_list/topic_card.ejs +21 -9
  24. package/layout/_partial/main/post_list/wiki_card.ejs +49 -10
  25. package/layout/_partial/scripts/defines.ejs +2 -8
  26. package/layout/_partial/scripts/lazyload.ejs +0 -3
  27. package/layout/_partial/scripts.ejs +1 -0
  28. package/layout/_partial/sidebar/index_leftbar.ejs +12 -2
  29. package/layout/_partial/sidebar/logo.ejs +1 -1
  30. package/layout/_partial/sidebar/menu.ejs +21 -23
  31. package/layout/_partial/widgets/components/linklist.ejs +23 -21
  32. package/layout/_partial/widgets/linklist.ejs +7 -12
  33. package/layout/_partial/widgets/recent.ejs +52 -41
  34. package/layout/_partial/widgets/related.ejs +47 -36
  35. package/layout/_partial/widgets/tagtree.ejs +70 -54
  36. package/layout/_partial/widgets/toc.ejs +37 -62
  37. package/layout/_partial/widgets/tree.ejs +38 -51
  38. package/layout/_plugins/mermaid.ejs +3 -4
  39. package/layout/archive.ejs +11 -20
  40. package/layout/collection-preview.ejs +60 -0
  41. package/layout/index_topic.ejs +12 -6
  42. package/layout/index_wiki.ejs +49 -3
  43. package/layout/layout.ejs +4 -3
  44. package/package.json +1 -1
  45. package/scripts/events/index.js +0 -2
  46. package/scripts/generators/stellar-icons.js +1 -1
  47. package/scripts/lib/subtitle.js +5 -1
  48. package/scripts/tags/index.js +1 -0
  49. package/scripts/tags/lib/about.js +1 -1
  50. package/scripts/tags/lib/albums.js +1 -1
  51. package/scripts/tags/lib/banner.js +1 -1
  52. package/scripts/tags/lib/dropdown.js +64 -0
  53. package/scripts/tags/lib/friends.js +1 -1
  54. package/scripts/tags/lib/gallery.js +3 -3
  55. package/scripts/tags/lib/image.js +1 -1
  56. package/scripts/tags/lib/posters.js +1 -1
  57. package/scripts/tags/lib/sites.js +8 -4
  58. package/source/css/_common/base.styl +4 -4
  59. package/source/css/_common/blockquote.styl +2 -2
  60. package/source/css/_common/dropdown.styl +132 -0
  61. package/source/css/_common/html.styl +1 -1
  62. package/source/css/_common/loading.styl +5 -2
  63. package/source/css/_common/title.styl +8 -8
  64. package/source/css/_components/collection.styl +188 -0
  65. package/source/css/_components/layout.styl +1 -1
  66. package/source/css/_components/list.styl +44 -46
  67. package/source/css/_components/md.styl +3 -3
  68. package/source/css/_components/page-transition.styl +22 -0
  69. package/source/css/_components/pages/archives.styl +19 -18
  70. package/source/css/_components/pages/article-indent.styl +2 -2
  71. package/source/css/_components/pages/article-story.styl +9 -5
  72. package/source/css/_components/pages/collection-preview.styl +68 -0
  73. package/source/css/_components/pages/notebook.styl +11 -9
  74. package/source/css/_components/partial/article-footer.styl +7 -4
  75. package/source/css/_components/partial/cover.styl +280 -1
  76. package/source/css/_components/partial/related.styl +10 -6
  77. package/source/css/_components/sidebar/footer.styl +65 -12
  78. package/source/css/_components/sidebar/nav-area.styl +6 -1
  79. package/source/css/_components/sidebar/search.styl +6 -2
  80. package/source/css/_components/tag-plugins/chat.styl +1 -1
  81. package/source/css/_components/tag-plugins/folders.styl +4 -4
  82. package/source/css/_components/tag-plugins/folding.styl +3 -3
  83. package/source/css/_components/tag-plugins/hashtag.styl +2 -3
  84. package/source/css/_components/tag-plugins/mdrender.styl +1 -1
  85. package/source/css/_components/tag-plugins/note.styl +4 -4
  86. package/source/css/_components/tag-plugins/poetry.styl +5 -5
  87. package/source/css/_components/tag-plugins/quot.styl +1 -2
  88. package/source/css/_components/tag-plugins/quote.styl +1 -1
  89. package/source/css/_components/tag-plugins/tabs.styl +2 -2
  90. package/source/css/_components/tag-plugins/timeline.styl +4 -4
  91. package/source/css/_components/widgets/markdown.styl +1 -14
  92. package/source/css/_components/widgets/timeline.styl +2 -2
  93. package/source/css/_components/widgets/toc.styl +22 -20
  94. package/source/css/_components/widgets/widgets.styl +13 -1
  95. package/source/css/_components/wiki-card.styl +209 -0
  96. package/source/css/_custom.styl +22 -20
  97. package/source/css/_plugins/lazyload.styl +8 -5
  98. package/source/css/comments/utterances.styl +2 -2
  99. package/source/css/plugins/mermaid.styl +31 -12
  100. package/source/js/icons.js +1 -1
  101. package/source/js/main.js +62 -6
  102. package/source/js/plugins/adaptive-text.js +46 -2
  103. package/source/js/plugins/dropdown.js +435 -0
  104. package/source/js/plugins/galaxy.js +423 -0
  105. package/source/js/search/algolia-search.js +1 -1
  106. package/source/js/search/local-search.js +1 -1
  107. package/source/js/services/ghinfo.js +31 -3
  108. package/source/js/services/siteinfo.js +26 -0
  109. package/source/js/services/sites.js +6 -2
  110. package/source/js/services.js +5 -2
  111. package/source/js/tagtree.js +7 -7
  112. package/source/js/utils.js +1 -1
  113. package/layout/_partial/widgets/components/link.ejs +0 -21
  114. package/source/css/_components/sidebar/menu.styl +0 -77
  115. package/source/css/_components/widgets/components.styl +0 -68
  116. package/source/css/_components/widgets/list.styl +0 -46
  117. package/source/css/_components/widgets/related.styl +0 -40
@@ -5,8 +5,8 @@
5
5
  &:before
6
6
  content: ''
7
7
  position absolute
8
- top: 6px
9
- bottom: 6px
8
+ top: 8px
9
+ bottom: 8px
10
10
  left: 0
11
11
  width: 4px
12
12
  background: var(--block)
@@ -16,13 +16,14 @@
16
16
  @media screen and (min-width: $device-laptop)
17
17
  background: var(--background)
18
18
 
19
- .l_left .widget-wrapper.toc
19
+ [data-ui-surface='glass'] .widget-wrapper.toc,
20
+ [data-ui-surface='card'] .widget-wrapper.toc
20
21
  @media screen and (min-width: $device-laptop)
21
22
  background: none
22
23
 
23
24
  // 目录基本样式
24
25
  .widget-wrapper.toc .toc
25
- --fsp: $fsp2
26
+ --fs-content: $fs-content-2
26
27
  padding: 0
27
28
  margin: 0
28
29
  position relative
@@ -35,7 +36,7 @@
35
36
  --padding-offset: calc(0 - var(--padding))
36
37
  padding: 4px var(--padding)
37
38
  margin: 0 var(--padding)
38
- color: var(--text-p3)
39
+ color: var(--ui-item-muted)
39
40
  display: block
40
41
  position relative
41
42
  border-radius: $border-bar
@@ -43,18 +44,19 @@
43
44
  &.active:before
44
45
  content: ''
45
46
  position absolute
46
- top: 6px
47
- bottom: 6px
47
+ top: 4px
48
+ bottom: 4px
48
49
  left: -8px
49
50
  width: 4px
50
51
  background: var(--theme)
51
52
  border-radius: 4px
52
53
  &:hover
53
- background: var(--block-border)
54
- color: var(--text)
54
+ background: var(--ui-adapter-bg-hover)
55
+ box-shadow: var(--ui-adapter-shadow-hover)
56
+ color: var(--ui-item-title)
55
57
 
56
58
  // 固定位置
57
- .l_right .widgets .widget-wrapper.toc
59
+ [data-ui-surface='sidebar'] .widgets .widget-wrapper.toc
58
60
  margin-top: 1rem
59
61
  position: sticky
60
62
  position: -webkit-sticky
@@ -78,22 +80,22 @@
78
80
  .widget-wrapper.toc .toc
79
81
  .toc-item
80
82
  font-weight: 500
81
- --fsp: $fsp1
83
+ --fs-content: $fs-content-1
82
84
  .toc-item .toc-item
83
85
  font-weight: 400
84
- --fsp: $fsp2
86
+ --fs-content: $fs-content-2
85
87
  ol
86
88
  padding-left: 0
87
89
  .toc-child .toc-link
88
- padding-left: 1.5rem
90
+ padding-left: calc(var(--gap-base) * 1)
89
91
  .toc-child .toc-child .toc-link
90
- padding-left: 2.5rem
92
+ padding-left: calc(var(--gap-base) * 2)
91
93
  .toc-child .toc-child .toc-child .toc-link
92
- padding-left: 3.5rem
94
+ padding-left: calc(var(--gap-base) * 3)
93
95
  .toc-child .toc-child .toc-child .toc-child .toc-link
94
- padding-left: 4.5rem
96
+ padding-left: calc(var(--gap-base) * 4)
95
97
  .toc-child .toc-child .toc-child .toc-child .toc-child .toc-link
96
- padding-left: 5rem
98
+ padding-left: calc(var(--gap-base) * 5)
97
99
 
98
100
  // 高亮样式
99
101
  .widget-wrapper.toc .toc a.toc-link.active
@@ -133,9 +135,9 @@
133
135
  grid-template-rows: 1fr
134
136
  trans1 all
135
137
  overflow hidden
136
- .l_right .widgets .widget-wrapper.toc .widget-header .cap-action:hover
138
+ [data-ui-surface='sidebar'] .widgets .widget-wrapper.toc .widget-header .cap-action:hover
137
139
  sidebar-light(var(--bg-a50))
138
- .l_right .widgets .widget-wrapper.toc.collapse
140
+ [data-ui-surface='sidebar'] .widgets .widget-wrapper.toc.collapse
139
141
  .widget-header .cap-action
140
142
  sidebar-light(var(--bg-a50))
141
143
  .widget-body
@@ -181,7 +183,7 @@
181
183
  padding-top: 32px
182
184
 
183
185
  @media screen and (max-width: $device-laptop)
184
- .l_right
186
+ [data-ui-surface='sidebar']
185
187
  blur-effect()
186
188
  .widgets
187
189
  .widget-wrapper.toc
@@ -44,7 +44,8 @@
44
44
  fill: var(--text-p2)
45
45
  &:hover
46
46
  color: var(--accent)
47
- sidebar-light(var(--bg-a50))
47
+ background: var(--ui-item-bg-hover)
48
+ box-shadow: var(--ui-item-shadow-hover)
48
49
  opacity 1
49
50
  svg
50
51
  fill: var(--accent)
@@ -55,11 +56,22 @@
55
56
  margin-top: .5em
56
57
  margin-bottom: .5em
57
58
  line-height: 1.5
59
+ >.ui-collection,
60
+ >.widget-section>.ui-collection
61
+ min-width: 0
58
62
 
59
63
 
60
64
  .widget-wrapper
61
65
  display: block
62
66
  margin-top: 32px
67
+ .widget-section+.widget-section
68
+ margin-top: 24px
69
+
70
+ .widget-wrapper.markdown
71
+ --ui-item-bg: var(--block)
72
+
73
+ [data-ui-surface='glass'] .widget-wrapper.markdown
74
+ --ui-item-bg: var(--bg-a10)
63
75
 
64
76
  .l_left .widgets
65
77
  padding-bottom: 64px
@@ -0,0 +1,209 @@
1
+ // Wiki 列表卡片独立组件:不复用文章 Hero 的 .cover 或 cover-overlay()。
2
+ .post-list.wiki
3
+ display: grid
4
+ // Nested min() in minmax() is dropped by older WebKit, which leaves only
5
+ // the grid's implicit single column.
6
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr))
7
+ gap: 1rem
8
+ .post-card-wrap
9
+ width: 100%
10
+ margin: 0
11
+ border-radius: $border-card-l
12
+ box-shadow: $boxshadow-card
13
+ @media screen and (max-width: $device-mobile)
14
+ grid-template-columns: minmax(0, 1fr)
15
+
16
+ .post-list.wiki .wiki-card
17
+ display: block
18
+ position: relative
19
+ z-index: 0
20
+ overflow: hidden
21
+ border-radius: $border-card-l
22
+ background: var(--card)
23
+ --wiki-img-br: 100%
24
+ --wiki-img-sat: 100%
25
+ --wiki-blur-sat: 150%
26
+ --wiki-overlay-color: var(--theme, #4f7cff)
27
+ // 边框与底部蒙版同源,但额外提高 20 个明度点,悬浮反馈更清晰。
28
+ --wiki-border-color: var(--theme, #4f7cff)
29
+ &.no-cover
30
+ --wiki-border-color: var(--block-border)
31
+ @supports not (corner-shape: superellipse(1))
32
+ clip-path: 'inset(0 round %s)' % $border-card-l
33
+ &:after
34
+ content: ''
35
+ position: absolute
36
+ inset: 0
37
+ z-index: 3
38
+ border: 2px solid transparent
39
+ border-radius: inherit
40
+ corner-shape: $corner-shape
41
+ pointer-events: none
42
+ transition: border-color .2s ease-out
43
+ &:hover
44
+ --wiki-img-br: 75%
45
+ --wiki-img-sat: 120%
46
+ --wiki-blur-sat: 200%
47
+ &:after
48
+ border-color: var(--wiki-border-color)
49
+ .wiki-card-cover > img
50
+ transform: scale(1.05)
51
+ .wiki-card-cover:before
52
+ transform: translateZ(0) scale(1.05)
53
+
54
+ .wiki-card-content
55
+ padding: 0
56
+
57
+ .wiki-card-cover
58
+ position: relative
59
+ min-height: 240px
60
+ overflow: hidden
61
+ aspect-ratio: 3 / 4
62
+ background-image: var(--cover-url)
63
+ background-size: cover
64
+ background-position: center
65
+ // Today 内容层:同图模糊覆盖下半部,主题色从中部开始渐显,到最底部才完全不透明。
66
+ > img
67
+ position: absolute
68
+ inset: 0
69
+ z-index: 0
70
+ width: 100%
71
+ height: 100%
72
+ object-fit: cover
73
+ filter: brightness(var(--wiki-img-br)) saturate(var(--wiki-img-sat))
74
+ transform: translateZ(0)
75
+ transition: all .2s ease-out, transform 1.5s ease-out
76
+ &:before
77
+ content: ''
78
+ position: absolute
79
+ inset: 0
80
+ z-index: 1
81
+ background-image: var(--cover-url)
82
+ background-size: cover
83
+ background-position: center
84
+ filter: brightness(var(--wiki-img-br)) saturate(var(--wiki-img-sat)) blur(1.5rem) saturate(var(--wiki-blur-sat))
85
+ mask: linear-gradient(to top, black, rgba(black, .75) 26%, transparent 52%)
86
+ -webkit-mask: linear-gradient(to top, black, rgba(black, .75) 26%, transparent 52%)
87
+ transform: translateZ(0)
88
+ pointer-events: none
89
+ opacity: 0
90
+ transition: opacity .2s ease-out, filter .2s ease-out, transform .5s ease-out
91
+ &:after
92
+ content: ''
93
+ position: absolute
94
+ inset: 0
95
+ z-index: 1
96
+ pointer-events: none
97
+ background-image: linear-gradient(to bottom, transparent 50%, var(--wiki-overlay-color) 100%)
98
+ opacity: 0
99
+ transition: opacity .2s ease-out
100
+ &.no-cover
101
+ background: var(--card)
102
+ &:before, &:after
103
+ display: none
104
+ &.cover-error > img
105
+ display: none
106
+
107
+ .post-list.wiki .wiki-card.cover-loaded .wiki-card-cover:not(.no-cover)
108
+ &:before, &:after
109
+ opacity: 1
110
+
111
+ .wiki-card-info
112
+ display: flex
113
+ position: absolute
114
+ z-index: 2
115
+ right: 0
116
+ bottom: 0
117
+ left: 0
118
+ flex-direction: column
119
+ justify-content: flex-end
120
+ box-sizing: border-box
121
+ color: var(--text-banner, white)
122
+ @media screen and (max-width: $device-mobile)
123
+ .wiki-card-summary
124
+ padding: .75rem
125
+
126
+ .wiki-card-cover.no-cover .wiki-card-info
127
+ color: var(--text)
128
+ .wiki-meta, .project-subtitle
129
+ color: var(--text-p2)
130
+
131
+ .wiki-card-info
132
+ .wiki-card-summary
133
+ padding: 1rem
134
+ .headline
135
+ margin: .5rem 0
136
+ font-weight: 700
137
+ line-height: 1.2
138
+ color: inherit
139
+ @media screen and (max-width: $device-mobile)
140
+ .headline
141
+ margin: .375rem 0
142
+ .wiki-meta
143
+ display: flex
144
+ flex-wrap: wrap
145
+ align-items: center
146
+ gap: .5rem 1rem
147
+ min-height: 1.25rem
148
+ color: var(--text-banner-theme, inherit)
149
+ font-size: $fs-13
150
+ line-height: 1.2
151
+ .wiki-available
152
+ display: inline-flex
153
+ flex-wrap: wrap
154
+ align-items: center
155
+ gap: 4px
156
+ .wiki-available, .wiki-stars
157
+ svg
158
+ flex: none
159
+ width: 1em
160
+ height: 1em
161
+ vertical-align: middle
162
+ .wiki-stars
163
+ display: none
164
+ align-items: center
165
+ gap: 4px
166
+ &.loaded
167
+ display: inline-flex
168
+ .wiki-project
169
+ display: flex
170
+ align-items: center
171
+ gap: 10px
172
+ margin-top: auto
173
+ padding: .75rem 1rem 1rem
174
+ background: rgba(black, .1)
175
+ line-height: 1.2
176
+ @media screen and (max-width: $device-mobile)
177
+ padding: .625rem .75rem .75rem
178
+ .project-icon
179
+ display: flex
180
+ flex: none
181
+ align-items: center
182
+ justify-content: center
183
+ width: 2.5rem
184
+ height: 2.5rem
185
+ overflow: hidden
186
+ border-radius: 30%
187
+ background: var(--block)
188
+ color: var(--text-p2)
189
+ img
190
+ width: 100%
191
+ height: 100%
192
+ object-fit: cover
193
+ svg
194
+ width: 1.5rem
195
+ height: 1.5rem
196
+ .project-text
197
+ min-width: 0
198
+ flex: 1
199
+ .project-name, .project-subtitle
200
+ overflow: hidden
201
+ text-overflow: ellipsis
202
+ white-space: nowrap
203
+ .project-name
204
+ font-size: $fs-14
205
+ font-weight: 600
206
+ .project-subtitle
207
+ margin-top: 3px
208
+ color: var(--text-banner-theme, inherit)
209
+ font-size: $fs-13
@@ -8,25 +8,24 @@ $ff-codeblock = convert(hexo-config('style.font-family.codeblock'))
8
8
 
9
9
  // font size
10
10
  $fs-root = convert(hexo-config('style.font-size.root'))
11
- $fs-15 = .9375rem
12
- $fs-14 = .875rem
13
- $fs-13 = .8125rem
14
- $fs-12 = .75rem
11
+ $fs-15 = 'calc(%s - 1px)' % var(--fs-content-base)
12
+ $fs-14 = 'calc(%s - 2px)' % var(--fs-content-base)
13
+ $fs-13 = 'calc(%s - 3px)' % var(--fs-content-base)
14
+ $fs-12 = 'calc(%s - 4px)' % var(--fs-content-base)
15
15
 
16
- $fs-body = convert(hexo-config('style.font-size.body'))
17
16
  $fs-code = convert(hexo-config('style.font-size.code'))
18
17
  $fs-codeblock = convert(hexo-config('style.font-size.codeblock'))
19
18
 
20
- $fsh1 = 'calc(%s + 9px)' % $fs-body
21
- $fsh2 = 'calc(%s + 11px)' % $fs-body
22
- $fsh3 = 'calc(%s + 7px)' % $fs-body
23
- $fsh4 = 'calc(%s + 4px)' % $fs-body
24
- $fsh5 = 'calc(%s + 2px)' % $fs-body
19
+ $fsh1 = 'calc(%s + 9px)' % var(--fs-content-base)
20
+ $fsh2 = 'calc(%s + 11px)' % var(--fs-content-base)
21
+ $fsh3 = 'calc(%s + 7px)' % var(--fs-content-base)
22
+ $fsh4 = 'calc(%s + 4px)' % var(--fs-content-base)
23
+ $fsh5 = 'calc(%s + 2px)' % var(--fs-content-base)
25
24
 
26
- $fsp0 = 'calc(%s - 0px)' % $fs-body
27
- $fsp1 = 'calc(%s - 1px)' % $fs-body
28
- $fsp2 = 'calc(%s - 2px)' % $fs-body
29
- $fsp3 = 'calc(%s - 3px)' % $fs-body
25
+ $fs-content-0 = 'calc(%s - 0px)' % var(--fs-content-base)
26
+ $fs-content-1 = 'calc(%s - 1px)' % var(--fs-content-base)
27
+ $fs-content-2 = 'calc(%s - 2px)' % var(--fs-content-base)
28
+ $fs-content-3 = 'calc(%s - 3px)' % var(--fs-content-base)
30
29
 
31
30
  // site main
32
31
  $site-background-image = hexo-config('style.site.background-image')
@@ -56,11 +55,13 @@ $corner-shape = convert(hexo-config('style.corner-shape'))
56
55
 
57
56
  // 可以动态变化的属性
58
57
  :root
58
+ --fs-root: $fs-root
59
+ --fs-content-base: var(--fs-root)
60
+ --fs-content: var(--fs-content-base)
59
61
  --width-main: 720px
60
- --fsp: $fs-body
61
- --fsh2: 'calc(%s + 11px)' % var(--fsp)
62
- --fsh3: 'calc(%s + 7px)' % var(--fsp)
63
- --fsh4: 'calc(%s + 4px)' % var(--fsp)
62
+ --fsh2: 'calc(%s + 11px)' % var(--fs-content)
63
+ --fsh3: 'calc(%s + 7px)' % var(--fs-content)
64
+ --fsh4: 'calc(%s + 4px)' % var(--fs-content)
64
65
 
65
66
  // 侧边栏文字内容宽度
66
67
  --side-content-width: 224px
@@ -73,8 +74,8 @@ $corner-shape = convert(hexo-config('style.corner-shape'))
73
74
  // 右栏宽度增量(在 --width-sidebar 基础上加宽)
74
75
  --rightbar-width-extra: calc(var(--gap-base) * 2)
75
76
 
76
- --gap-p: 'calc(%s + 4px)' % $fs-body // gap for paragraph
77
- --gap-p-compact: 'calc(%s * 0.75)' % $fs-body
77
+ --gap-p: 'calc(%s + 4px)' % var(--fs-content-base) // gap for paragraph
78
+ --gap-p-compact: 'calc(%s * 0.75)' % var(--fs-content-base)
78
79
  // desktop 2k or larger
79
80
  @media screen and (min-width: $device-2k)
80
81
  --width-main: 780px
@@ -85,6 +86,7 @@ $corner-shape = convert(hexo-config('style.corner-shape'))
85
86
  @media screen and (max-width: $device-tablet)
86
87
  --side-content-width: 188px
87
88
  @media screen and (max-width: $device-mobile-max)
89
+ --fs-root: 'calc(%s + 2px)' % $fs-root
88
90
  --side-content-width: 224px
89
91
 
90
92
  // shadow
@@ -18,18 +18,21 @@ img:not([src])
18
18
  min-height: 4rem
19
19
 
20
20
  // 加载占位动画
21
- img.lazy.loading + .lazy-icon
22
- position: absolute
21
+ .lazy-icon
23
22
  width: $loadingImageSize
24
23
  height: $loadingImageSize
25
24
  max-width: 100%
26
25
  max-height: 100%
26
+ // 蒙版上色:SVG 作为 mask(只取形状),颜色由 background-color 提供,
27
+ // 避免 currentColor 在 SVG-as-image 场景(Safari)退化为黑色
28
+ background-color: var(--theme)
29
+ svg-mask-icon(var(--icon-loading, url("https://api.iconify.design/eos-icons:three-dots-loading.svg?color=%231cd0fd")))
30
+
31
+ img.lazy.loading + .lazy-icon
32
+ position: absolute
27
33
  top: 50%
28
34
  left: 50%
29
35
  transform: translateX(-50%) translateY(-50%)
30
- background-size: contain
31
- background-repeat: no-repeat
32
- background-position: center
33
36
 
34
37
  // 加载完成
35
38
  img.lazy.loaded + .lazy-icon,
@@ -2,5 +2,5 @@
2
2
  margin: 0 -4px
3
3
  width: 'calc(100% + %s)' % 8px
4
4
 
5
- .related-wrap#comments .cmt-body svg.loading
6
- top: 62px
5
+ .related-wrap#comments .cmt-body .lazy-icon
6
+ top: 62px
@@ -7,17 +7,36 @@ pre.mermaid
7
7
  justify-content: center;
8
8
  font-family: $ff-body
9
9
 
10
- .mermaid span,text
10
+ .mermaid span,
11
+ .mermaid text
11
12
  font-family: $ff-body
12
13
 
13
14
  .mermaid .edgeLabel
14
15
  padding: 4px
15
16
  background-color: var(--background) !important
17
+ color: var(--text-p1) !important
18
+
19
+ .mermaid .edgeLabel text,
20
+ .mermaid .label text,
21
+ .mermaid .nodeLabel,
22
+ .mermaid .cluster-label text,
23
+ .mermaid .cluster-label span
24
+ fill: var(--text-p1) !important
25
+ color: var(--text-p1) !important
16
26
 
17
27
  .mermaid rect.basic.label-container
18
28
  stroke: var(--block-border) !important
19
29
  fill: var(--block) !important
20
30
 
31
+ .mermaid .node rect,
32
+ .mermaid .node circle,
33
+ .mermaid .node ellipse,
34
+ .mermaid .node polygon,
35
+ .mermaid .node path,
36
+ .mermaid .cluster rect
37
+ stroke: var(--block-border) !important
38
+ fill: var(--block) !important
39
+
21
40
  _dark_mermaid()
22
41
  .mermaid
23
42
  fill: #ccc !important
@@ -42,21 +61,21 @@ _dark_mermaid()
42
61
 
43
62
 
44
63
  .mermaid .label
45
- color: #ccc !important
64
+ color: var(--text-p1) !important
46
65
 
47
66
 
48
67
  .mermaid .cluster-label text
49
- fill: #F9FFFE !important
68
+ fill: var(--text-p1) !important
50
69
 
51
70
 
52
71
  .mermaid .cluster-label span
53
- color: #F9FFFE !important
72
+ color: var(--text-p1) !important
54
73
 
55
74
 
56
75
  .mermaid .label text,
57
76
  .mermaid span
58
- fill: #ccc !important
59
- color: #ccc !important
77
+ fill: var(--text-p1) !important
78
+ color: var(--text-p1) !important
60
79
 
61
80
 
62
81
  .mermaid .node rect,
@@ -64,8 +83,8 @@ _dark_mermaid()
64
83
  .mermaid .node ellipse,
65
84
  .mermaid .node polygon,
66
85
  .mermaid .node path
67
- fill: #1f2020 !important
68
- stroke: #81B1DB !important
86
+ fill: var(--block) !important
87
+ stroke: var(--block-border) !important
69
88
 
70
89
 
71
90
  .mermaid .arrowheadPath
@@ -90,16 +109,16 @@ _dark_mermaid()
90
109
 
91
110
 
92
111
  .mermaid .cluster rect
93
- fill: hsl(180, 1.5873015873%, 28.3529411765%) !important
94
- stroke: rgba(255, 255, 255, 0.25) !important
112
+ fill: var(--block) !important
113
+ stroke: var(--block-border) !important
95
114
 
96
115
 
97
116
  .mermaid .cluster text
98
- fill: #F9FFFE !important
117
+ fill: var(--text-p1) !important
99
118
 
100
119
 
101
120
  .mermaid .cluster span
102
- color: #F9FFFE !important
121
+ color: var(--text-p1) !important
103
122
 
104
123
 
105
124
  .mermaid div.mermaidTooltip
@@ -4,7 +4,7 @@
4
4
  * 服务端 icon() 对非首屏 SVG 图标输出 <svg class="icon" data-icon="ns:key"> 占位符,
5
5
  * 本脚本按命名空间拉取构建期生成的 js/icons/{ns}.json,成功后原位替换为完整内联 SVG,
6
6
  * 最终 DOM 与全量内联一致,现有 CSS 钩子(搜索三态、菜单渐变、chat 着色等)不受影响。
7
- * 首屏关键图标(搜索、菜单、leftbar/rightbar、goback)由模板内联,不经过本脚本。
7
+ * 首屏关键图标(搜索、菜单、leftbar/rightbar、arrow-left)由模板内联,不经过本脚本。
8
8
  */
9
9
  (function () {
10
10
  'use strict';
package/source/js/main.js CHANGED
@@ -177,7 +177,7 @@ function rebuildToc(scope) {
177
177
  return;
178
178
  }
179
179
  const ol = document.createElement('ol');
180
- ol.className = 'toc';
180
+ ol.className = 'toc ui-collection-adapter';
181
181
  const stack = [];
182
182
  headings.forEach(function (h) {
183
183
  const id = h.id;
@@ -372,6 +372,56 @@ const init = {
372
372
  }
373
373
  });
374
374
  },
375
+ wikiCover: () => {
376
+ document.querySelectorAll('.wiki-cover-terminal').forEach(function (terminal) {
377
+ const code = terminal.querySelector('pre code');
378
+ const tabs = terminal.querySelectorAll('[role="tab"]');
379
+ function renderCodes(value) {
380
+ const lines = value.split(/\r?\n/).filter(function (line) {
381
+ return line.trim().length > 0;
382
+ });
383
+ terminal.dataset.codes = lines.join('\n');
384
+ code.innerHTML = '';
385
+ lines.forEach(function (line) {
386
+ const row = document.createElement('span');
387
+ row.textContent = line;
388
+ code.appendChild(row);
389
+ });
390
+ }
391
+ if (tabs.length > 0) {
392
+ renderCodes(tabs[0].getAttribute('data-codes') || '');
393
+ }
394
+ tabs.forEach(function (tab) {
395
+ tab.addEventListener('click', function () {
396
+ tabs.forEach(function (item) {
397
+ const active = item === tab;
398
+ item.classList.toggle('active', active);
399
+ item.setAttribute('aria-selected', active ? 'true' : 'false');
400
+ });
401
+ renderCodes(tab.getAttribute('data-codes') || '');
402
+ });
403
+ });
404
+ const copy = terminal.querySelector('.wiki-cover-copy');
405
+ if (copy) {
406
+ copy.addEventListener('click', function () {
407
+ const value = terminal.dataset.codes || '';
408
+ if (!value || !navigator.clipboard) return;
409
+ navigator.clipboard.writeText(value).then(function () {
410
+ hud.toast(copy.getAttribute('data-copy-message') || 'Copied', 2500);
411
+ }).catch(function () {});
412
+ });
413
+ }
414
+ });
415
+
416
+ const galaxyCanvases = document.querySelectorAll('.wiki-cover-background.galaxy canvas');
417
+ const reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
418
+ if (reduceMotion || galaxyCanvases.length === 0) return;
419
+ utils.js('/js/plugins/galaxy.js').then(function () {
420
+ if (stellar.galaxy && typeof stellar.galaxy.mountAll === 'function') {
421
+ stellar.galaxy.mountAll(galaxyCanvases);
422
+ }
423
+ }).catch(function () {});
424
+ },
375
425
  leftbarScroll: () => {
376
426
  const container = document.querySelector('.l_left .widgets');
377
427
  if (container == null) {
@@ -380,7 +430,7 @@ const init = {
380
430
  const PREFIX = 'Stellar.leftbarScroll.';
381
431
  const encode = (s) => encodeURIComponent(String(s || ''));
382
432
  function scope() {
383
- const wikiEl = document.querySelector('.doc-tree[data-wiki]');
433
+ const wikiEl = document.querySelector('.doc-tree-widget[data-wiki]');
384
434
  if (wikiEl != null) {
385
435
  return 'wiki:' + encode(wikiEl.getAttribute('data-wiki'));
386
436
  }
@@ -409,7 +459,7 @@ const init = {
409
459
  return;
410
460
  }
411
461
  container.scrollTop = parseInt(value, 10) || 0;
412
- const link = container.querySelector('a.link.active');
462
+ const link = container.querySelector('.ui-collection__item.is-active');
413
463
  if (link == null) {
414
464
  return;
415
465
  }
@@ -426,22 +476,27 @@ const init = {
426
476
  } catch (e) {}
427
477
  },
428
478
  navbarPin: () => {
429
- // 列表页 navbar top 背景条状态切换:未吸顶为卡片样式(var(--card) + 文章卡片同款阴影),
430
- // 吸顶后恢复玻璃效果。在吸顶边界切换 .pinned 类,视觉由 CSS 控制。
479
+ // 列表页 navbar top 背景条状态切换:未滚动/未吸顶为卡片样式(var(--card) + 文章卡片同款阴影),
480
+ // 页面滚动达到阈值且吸顶后恢复玻璃效果。在吸顶边界切换 .pinned 类,视觉由 CSS 控制。
431
481
  // 吸顶判定直接测 navbar 的实际视口位置,而非用 scrollY 推算:
432
482
  // 移动端浏览器顶栏伸缩会改变 scrollY(展开顶栏时 scrollY 减小),
433
483
  // 即使 navbar 仍吸顶也可能跌破阈值,导致玻璃效果误消失。
484
+ // 无轮播区页面(如 wiki)的 navbar 在页面顶部即已吸顶,需额外要求页面实际滚动达到阈值,
485
+ // 否则默认保持卡片样式;回到顶部(滚动小于阈值)恢复卡片。
434
486
  const navbars = document.querySelectorAll('.navbar.top');
435
487
  if (navbars.length === 0) {
436
488
  return;
437
489
  }
438
490
  // 视口顶部允许的偏差(px),吸收亚像素/取整误差
439
491
  const TOLERANCE = 2;
492
+ // 页面滚动阈值(px):未滚动时保持卡片样式,滚动达到该值后才切换玻璃效果
493
+ const SCROLL_THRESHOLD = 2;
440
494
  let states = [];
441
495
  function update() {
496
+ const scrolled = window.scrollY >= SCROLL_THRESHOLD;
442
497
  states.forEach((state) => {
443
498
  const top = state.navbar.getBoundingClientRect().top;
444
- state.bar.classList.toggle('pinned', top <= state.stickyTop + TOLERANCE);
499
+ state.bar.classList.toggle('pinned', scrolled && top <= state.stickyTop + TOLERANCE);
445
500
  });
446
501
  }
447
502
  function measure() {
@@ -621,6 +676,7 @@ stellar.initPage = function () {
621
676
  init.toc();
622
677
  init.sidebar();
623
678
  init.wikiStart();
679
+ init.wikiCover();
624
680
  init.leftbarScroll();
625
681
  init.navbarPin();
626
682
  init.relativeDate(document.querySelectorAll('#post-meta time'));