hexo-theme-stellar 1.32.2 → 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.
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.2'
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 ########
@@ -666,7 +674,7 @@ style:
666
674
  next: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/arrow/064b95430caf4.svg
667
675
  error_page: https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/404/1c830bfcd517d.svg
668
676
  site: # 使用 background-image 后,blur 设置才有效
669
- # background-image: 'url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.14/image/site-bg1@small.webp)'
677
+ # background-image: url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.14/image/site-bg1@small.webp)
670
678
  blur-px: 100px
671
679
  blur-bg: var(--bg-a75)
672
680
  blur-sat: 300%
@@ -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
  }
@@ -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
  }
@@ -109,7 +109,7 @@ function layoutDiv() {
109
109
  var el = ``
110
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
  }
@@ -4,7 +4,7 @@
4
4
  // Set the options globally
5
5
  // to make LazyLoad self-initialize
6
6
  window.lazyLoadOptions = {
7
- elements_selector: ".lazy",
7
+ elements_selector: ".lazy, .lazyload",
8
8
  callback_loaded: (el) => {
9
9
  el.classList.add('loaded');
10
10
  const wrapper = el.closest('.lazy-box');
@@ -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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-stellar",
3
- "version": "1.32.2",
3
+ "version": "1.32.3",
4
4
  "description": "Elegant and powerful theme for Hexo.",
5
5
  "main": "package.json",
6
6
  "scripts": {
@@ -27,7 +27,10 @@ module.exports = ctx => function(args) {
27
27
  if (item?.url && item?.title) {
28
28
  el += `<div class="grid-cell user-card">`
29
29
  el += `<a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="${item.url}">`
30
- el += `<img src="${item.icon || item.avatar || ctx.theme.config.default.avatar}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${ctx.theme.config.default.avatar}&quot;;"/>`
30
+ el += `<div class="lazy-box icon">`
31
+ el += `<img class="lazy" data-src="${item.icon || item.avatar || ctx.theme.config.default.avatar}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${ctx.theme.config.default.avatar}&quot;;"/>`
32
+ el += `<div class="lazy-icon" style="background-image:url(&quot;${ctx.theme.config.default.loading}&quot;);"></div>`
33
+ el += `</div>`
31
34
  el += `<div class="name">`
32
35
  el += `<span>${item.title}</span>`
33
36
  el += `</div>`
@@ -11,7 +11,7 @@ module.exports = ctx => function(args) {
11
11
  var args = ctx.args.map(args, ['repo', 'api', 'size'], ['group'])
12
12
  const host = ctx.theme.config.api_host.ghraw
13
13
  if (args.size == null) {
14
- args.size = 'm'
14
+ args.size = 'xs'
15
15
  }
16
16
  var api
17
17
  if (args.api) {
@@ -32,12 +32,12 @@ module.exports = ctx => function(args) {
32
32
  el += `<div class="grid-cell site-card">`
33
33
  el += `<a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="${item.url}">`
34
34
  el += `<div class="lazy-box snapshot">`
35
- el += `<img src="${item.cover || item.snapshot || item.screenshot || ('https://image.thum.io/get/width/1280/crop/720/' + item.url)}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${ctx.theme.config.default.cover}&quot;;"/>`
35
+ el += `<img class="lazy" data-src="${item.cover || item.snapshot || item.screenshot || ('https://image.thum.io/get/width/1280/crop/720/' + item.url)}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${ctx.theme.config.default.cover}&quot;;"/>`
36
36
  el += `<div class="lazy-icon" style="background-image:url(&quot;${ctx.theme.config.default.loading}&quot;);"></div>`
37
37
  el += `</div>`
38
38
  el += `<div class="info">`
39
39
  el += `<div class="lazy-box icon">`
40
- el += `<img src="${item.icon || item.avatar || ctx.theme.config.default.link}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${item.icon || item.avatar || ctx.theme.config.default.link}&quot;;"/>`
40
+ el += `<img class="lazy" data-src="${item.icon || item.avatar || ctx.theme.config.default.link}" onerror="javascript:this.removeAttribute(&quot;data-src&quot;);this.src=&quot;${item.icon || item.avatar || ctx.theme.config.default.link}&quot;;"/>`
41
41
  el += `<div class="lazy-icon" style="background-image:url(&quot;${ctx.theme.config.default.loading}&quot;);"></div>`
42
42
  el += `</div>`
43
43
  el += `<span class="title">${item.title}</span>`
@@ -20,8 +20,8 @@ body>.sitebg
20
20
  right: 0
21
21
  bottom: 0
22
22
  background-size: cover
23
- if $site-background
24
- background-image: convert($site-background)
23
+ if $site-background-image
24
+ background-image: convert($site-background-image)
25
25
  .siteblur
26
26
  width: 100%
27
27
  height: 100%
@@ -1,7 +1,7 @@
1
1
  .l_body[type=story] .md-text.content
2
2
  --fsp: 'calc(%s + 1px)' % $fs-body
3
3
  --gap-p: 2rem
4
- div.tag-plugin,p>img
4
+ >div.tag-plugin,>p>img
5
5
  margin-top: 2.4rem
6
6
  margin-bottom: 2.4rem
7
7
  // 段落标题
@@ -19,6 +19,7 @@
19
19
  position: relative
20
20
  // override
21
21
  .md-text.content .tag-plugin.quot
22
+ text-wrap: balance
22
23
  h1,h2
23
24
  font-size: $fsh2
24
25
  font-weight: 900
@@ -11,6 +11,11 @@
11
11
  width: 4px
12
12
  background: var(--block)
13
13
  border-radius: 4px
14
+
15
+ if !$site-background-image
16
+ @media screen and (min-width: $device-laptop)
17
+ background: var(--background)
18
+
14
19
 
15
20
  // 目录基本样式
16
21
  .widget-wrapper.toc .toc
@@ -178,6 +183,6 @@
178
183
  color: var(--text-p2)
179
184
  .widget-wrapper.toc .widget-footer
180
185
  a
181
- background: var(--bg-a100)
186
+ background: var(--block)
182
187
  a+a
183
188
  margin-top: 4px
@@ -29,7 +29,7 @@ $fsp2 = 'calc(%s - 2px)' % $fs-body
29
29
  $fsp3 = 'calc(%s - 3px)' % $fs-body
30
30
 
31
31
  // site main
32
- $site-background = hexo-config('style.site.background-image')
32
+ $site-background-image = hexo-config('style.site.background-image')
33
33
  $leftbar-background-image = hexo-config('style.leftbar.background-image')
34
34
  $leftbar-background-color = hexo-config('style.leftbar.background-color')
35
35
 
@@ -66,7 +66,7 @@ x-set-text-colors($scheme, $p0 = 1, $p1 = 0.8, $p2 = 0.7, $p3 = 0.5, $p4 = 0.4)
66
66
  dynamic-theme-light()
67
67
  $hue = $c-base-hue
68
68
  --background: x-hsla($hue, 20%, 98%, 1)
69
- --card: $site-background ? hsla(white, 0.5) : white
69
+ --card: $site-background-image ? hsla(white, 0.5) : white
70
70
 
71
71
  x-set-bg-colors('light')
72
72
  x-set-text-colors('light')
@@ -77,7 +77,7 @@ dynamic-theme-dark()
77
77
  --background: x-hsla($hue, 8%, 12%, 1)
78
78
  @media screen and (max-width: $device-mobile-max)
79
79
  --background: black
80
- --card: $site-background ? hsla(white, 0.25) : x-hsla($hue, 10%, 24%, 1)
80
+ --card: $site-background-image ? hsla(white, 0.25) : x-hsla($hue, 10%, 24%, 1)
81
81
 
82
82
  x-set-bg-colors('dark')
83
83
  x-set-text-colors('dark')
@@ -4,15 +4,15 @@ x-set-theme-colorful($scheme = 'light', $color, $text = true)
4
4
  x-set-theme-with-color($color)
5
5
  x-set-link-with-color($color)
6
6
  if $scheme == 'dark'
7
- --theme-border: x-hsla($hue, 50%, 24%)
7
+ --theme-border: x-hsla($hue, 40%, 24%)
8
8
  --theme-block: x-hsla($hue, 24%, 24%)
9
9
  --theme-mark: x-hsla($hue, 24%, 24%)
10
- --theme-codeblock: x-hsla($hue, 12%, 18%)
10
+ --theme-codeblock: x-hsla($hue, 12%, 24%)
11
11
  if text
12
12
  --text: x-hsla($hue, 50%, 75%, 1)
13
- --text-p1: x-hsla($hue, 50%, 75%, 0.8)
14
- --text-p2: x-hsla($hue, 80%, 80%, 0.7)
15
- --text-p3: x-hsla($hue, 80%, 80%, 0.5)
13
+ --text-p1: x-hsla($hue, 80%, 80%, 1)
14
+ --text-p2: x-hsla($hue, 80%, 80%, 0.8)
15
+ --text-p3: x-hsla($hue, 80%, 80%, 0.6)
16
16
  --text-p4: x-hsla($hue, 80%, 80%, 0.4)
17
17
  --link: x-hsla($hue, 80%, 60%, 1)
18
18
  --link-a20: x-hsla($hue, 80%, 60%, 0.2)
@@ -23,9 +23,9 @@ x-set-theme-colorful($scheme = 'light', $color, $text = true)
23
23
  --theme-codeblock: x-hsla($hue, 50%, 95%)
24
24
  if text
25
25
  --text: x-hsla($hue, 55%, 16%, 1)
26
- --text-p1: x-hsla($hue, 55%, 16%, 0.8)
27
- --text-p2: x-hsla($hue, 90%, 20%, 0.7)
28
- --text-p3: x-hsla($hue, 90%, 20%, 0.5)
26
+ --text-p1: x-hsla($hue, 90%, 20%, 1)
27
+ --text-p2: x-hsla($hue, 90%, 20%, 0.8)
28
+ --text-p3: x-hsla($hue, 90%, 20%, 0.6)
29
29
  --text-p4: x-hsla($hue, 90%, 20%, 0.4)
30
30
  --link: x-hsla($hue, 95%, 32%, 1)
31
31
  --link-a20: x-hsla($hue, 95%, 32%, 0.2)
@@ -70,6 +70,9 @@
70
70
  .atk-error-layer
71
71
  background: none
72
72
 
73
+ .with-fancybox .atk-content img:not([atk-emoticon])
74
+ cursor: zoom-in
75
+
73
76
  .cmt-body
74
77
  .artalk, .atk-layer-wrap, .artalk.atk-dark-mode, .atk-layer-wrap.atk-dark-mode
75
78
  --at-color-font: var(--text-p1)
@@ -77,7 +80,7 @@
77
80
  --at-color-sub: var(--text-p3)
78
81
  --at-color-grey: var(--text-p4)
79
82
  --at-color-meta: var(--text-p4)
80
- if $site-background
83
+ if $site-background-image
81
84
  --at-color-border: transparent
82
85
  else
83
86
  --at-color-border: var(--block-border)
@@ -47,7 +47,7 @@ img[data-ll-status].loaded
47
47
 
48
48
  // 加载失败
49
49
  img[data-ll-status].error
50
- min-width: $loadingImageSize
51
- min-height: $loadingImageSize
50
+ width: $loadingImageSize
51
+ height: $loadingImageSize
52
52
  &+.lazy-icon
53
53
  display: none