Hexo stellar 主题有段时间大改样式,当时没时间更新主题。感觉现在主题比较稳定了,终于找到时间把主题更新一下。由于stellar经过作者大改,我之前写的很多自定义样式都失效了。所以折腾了一上午,重新美化了一下。希望自己以后坚持每周都写一篇博客吧🐦。

博客界面

目前的博客样式

主页
主页
文章内
文章内

之前的历史快照

2023.09.26
2023.09.26
2023.11.05
2023.11.05

目前我是怎么发Hexo博客的

现在我基本是使用「思源笔记」来管理笔记和写博客,这是一个管理和编辑体验很好的双链笔记软件。思源笔记有一个「发布工具」插件,可以很便捷的把思源笔记里的文章上传到各个平台,非常省心,再结合思源笔记的数据库功能可以很方便的管理发布的文章。

发布工具
发布工具
用思源笔记的数据库来管理博客文章
用思源笔记的数据库来管理博客文章

代码更改记录

Markdown图片title标题失效

Markdown 的完整图片语法是 ![anchor text](img_src "title"),一些笔记软件像语雀、思源笔记目前都是支持解析title作为图片标题的,一些hexo主题如butterfly应该也是支持的(也是我提的建议)。

stellar之前是接受了我的pull request,可以解析Markdown的图片title语法作为图片标题,

但现在直接把解析Markdown标题的删掉了(见issue讨论代码改动)。

作为基本只用Markdown语法写博客的人来说,实在太不友好了,所以又把删掉的代码给加了回来。

并且改进了下 themes\stellar\scripts\filters\index.js,减少误替换的情况发生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
'use strict';

hexo.extend.filter.register('after_render:html', require('./lib/img_lazyload').processSite);
hexo.extend.filter.register('after_render:html', require('./lib/img_onerror').processSite);

function change_image(data) {
if (this.theme.config.tag_plugins.image.parse_markdown) {
// Step 1: 删除所有零宽空格字符
data.content = data.content.replace(/\u200B/g, '');

// Step 2: 修改正则表达式,只在行首或前面只有空格和缩进时替换图片链接
data.content = data.content.replace(
/^(?:\s*)!\[(.*?)\]\((.*?)\s*(?:"(.*?)")?\)/gm,
'{% image $2 $3 %}'
);
}
return data;
}



hexo.extend.filter.register('before_post_render', change_image, 9);

添加分类 widget

这样在主页就知道自己文章有多少分类了

/themes/stellar/layout/_partial/widgets/ 下新建 categories.ejs,填入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<% function layoutCategoriesDiv() { var el='' ; if (site.categories===undefined || site.categories.length===0) { return
el; } var opts=Object.assign({}, item); delete opts['title']; delete opts['layout']; opts.class='category ' ;
el+=`<widget class="widget-wrapper${scrollreveal(' ')} categories-widget">`;

if (item.title) {
el += '<div class="widget-header categories-header dis-select">';
el += '<span class="name">' + item.title + '</span>';
el += '</div>';
}

el += '<div class="widget-body">';
// Generate categories list
site.categories.each(function(category) {
el += `<div class="${opts.class}">`;
el += `<svg class="category-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
<path d="M18 10h-5" opacity=".5" />
<path d="M10 3h6.5c.464 0 .697 0 .892.026a3 3 0 0 1 2.582 2.582c.026.195.026.428.026.892"
opacity=".5" />
<path
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" />
</svg>`;
el += `<a href="${url_for(category.path)}">${category.name} (${category.length})</a>`;
el += `</div>`;
});
el += '</div>';
el += '</widget>'; // Close widget-wrapper
return el;
}
%>
<%- layoutCategoriesDiv() %>

themes/stellar/source/css/_layout/widgets/ 下新建 categories.styl 文件,填入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// categories widget 样式
.widget-wrapper.categories-widget .widget-body {
border-radius: $border-card;
padding: 12px 20px;
background: var(--alpha50); // 这里设置背景
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); // 添加阴影效果
}

// 每个分类的样式
.category
line-height: 1.5
margin: 8px 0
display: flex // 使用flex布局来确保图标和文本在同一行
align-items: center // 垂直居中对齐

.category-icon
width: 16px
height: 16px
vertical-align: middle
margin-right: 8px

.category a
display: inline-block // 链接以行内块方式显示
word-break: break-word
color: var(--text-p2)
font-family: system-ui
font-weight: 300
font-size: 16px
text-decoration: none
&:hover
color: $color-hover
text-decoration: underline

// Variables
$color-hover = #0366d6


参考:Stellar 主题中添加分类索引 Widget - 宇宙尽头的餐馆

随机文章按钮

创建 themes/stellar/scripts/helpers/random.js ,增加以下代码:

1
2
3
4
5
6
7
8
hexo.extend.filter.register('after_render:html', function (data) {
const posts = []
hexo.locals.get('posts').map(function (post) {
if (post.random !== false) posts.push(post.path)
})
data += `<script>var posts=${JSON.stringify(posts)};function toRandomPost(){ var randomPath = posts[Math.floor(Math.random()*posts.length)]; var encodedPath = encodeURIComponent(randomPath); window.open('/' + encodedPath, "_self"); };</script>`
return data
})

参考:Hexo Stellar 主题装修笔记 - 宇宙尽头的餐馆:随机文章按钮

备注:文章路径需要用encodeURIComponent来编码,否则如果文章路径里有连字符,没有在前面加上域名地址,导致打开失败。

增强标签显示

现在相比于分类我可能会更喜欢用标签,因为一篇文章可以打多个标签。我在思源笔记里管理笔记也是用管理链接的方式而弃用了文档树分类,所以标签更符合我管理笔记的习惯。stellar默认在文章列表只显示分类,对我来说就有点难受了。

主页文章列表添加标签

修改themes/stellar/layout/_partial/main/post_list/post_card.ejs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// cat
if (post.categories && post.categories.length > 0) {
if (post.layout === 'post' && post.categories && post.categories.length > 0) {
var cats = [];
if (post.categories) {
post.categories.forEach((cat, i) => {
cats.push(cat.name);
});
}
if (cats.length > 0) {
let cat = cats.shift();
el += '<span class="cap breadcrumb"' + category_color(cat) + '>';
el += icon('default:category')
el += `<span>${cat}</span>`
el += '</span>';
}
}
}
if (post.sticky) {
el += `<span class="pin">${icon('default:pin')}</span>`
}
el += '</div>';
// cat tags
el += '<div style="margin: 4px 0px;">';
if (post.tags && post.tags.length > 0) {
el += '<span class="cap tags">';

el += post.tags.map(tag => `<span style="background-color: var(--tag-bg-color); padding: 0px 6px; margin: 0px 5px 0px 0px;border-radius: 5px; color: var(--tag-text-color); line-height: 1.5;">#<span>${tag.name}</span></span>`).join('');

el += '</span>';
}

el += '</div>';
el += '</article>';
return el;

自定义样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 默认的浅色模式颜色 */
:root {
--tag-bg-color: #F2EEFD;
--tag-text-color: #835EEC;
}

/* 暗黑模式下的颜色 */
@media (prefers-color-scheme: dark) {
:root {
--tag-bg-color: #282433;
--tag-text-color: #A28BF2;
}
}


#post-meta {
font-size: 12px;
color: var(--text-p4); /* 或 --text-p2,设置为灰色 */
}

在文章页面添加标签显示

layout/_partial/main/navbar/article_banner.ejs 文件中,找到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 3.left.top: 面包屑导航
el += `<div class="flex-row" id="breadcrumb">`
// 首页
el += `<a class="cap breadcrumb" href="${url_for(config.root)}">${__("btn.home")}</a>`
if (theme.wiki.tree[page.wiki]) {
el += partial('breadcrumb/wiki')
} else if (page.layout == 'post') {
el += partial('breadcrumb/blog')
} else {
el += partial('breadcrumb/page')
}
// end 3.left.top
el += `</div>`

并在后面添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 在这里添加标签代码
if (page.layout == "post" && page.tags && page.tags.length > 0) {
el += '<div id="tag">'; // 将标签容器的创建移动到条件内部
el += ' <span>&nbsp标签:</span>';
el += list_categories(page.tags, {
class: "cap breadcrumb",
show_count: false,
separator: '&nbsp; ',
style: "none"
});
el += '&nbsp</div>';
}

参考:Hexo Stellar 主题装修笔记 - 宇宙尽头的餐馆:在文章页面添加标签显示

自定义css

文章内更新日期始终显示

1
2
3
4
/* 文章内更新日期始终显示 */
.bread-nav div#post-meta span.updated {
visibility: visible !important;
}

自定义滚动条样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* from https: //github.com/weekdaycare/weekdaycare.github.io/blob/main/css/scrollbar.css */

/* 滚动条 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}

::-webkit-scrollbar-track {
background-color: rgba(200, 155, 155, 0);
border-radius: 2em;
}

::-webkit-scrollbar-thumb {
background-color: #c3c0c1 !important;
/* background-image: -webkit-linear-gradient(45deg,
rgba(255, 255, 255, 0.4) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.4) 50%,
rgba(255, 255, 255, 0.4) 75%,
transparent 75%,
transparent) !important; */
border-radius: 2em;
}

::-webkit-scrollbar-corner {
background-color: transparent;
}

[data-theme="dark"] ::-webkit-scrollbar-thumb {
background-color: #1f1f1f !important;
}

限制代码块的最大高度

1
2
3
4
.md-text .highlight {
max-height: 800px;
overflow: auto;
}

链接样式优化

1
2
3
4
5
6
7
8
9
10
11
12
/* 文章内链接:为链接使用荧光笔下划线效果 */
/* 文章内链接 */
li:not([class]) a:not([class]),
p:not([class]) a:not([class]),
table a:not([class]) {
/*color: var(--theme-link);*/
padding-bottom: 3px; /* 增加底部padding */
padding-right: 1px;
margin-right: 2px;
color: var(--theme-link);
background: linear-gradient(0, var(--theme-link), var(--theme-link)) no-repeat center bottom / 100% 2px;
}

参考:Hexo Stellar 主题装修笔记 - 宇宙尽头的餐馆:超链接样式调整

添加最新评论组件

参考:Stellar展示最新评论 - 星日语 (weekdaycare.cn)

vercel app准备

  1. 部署 repo 至 Vercel:Achuan-2/recent-comment (github.com)

  2. 需要在vercel中设置环境变量

    name description
    LIMIT 获取数量
    GITHUB_REPO_OWNER Github用户名
    GITHUB_REPO_NAME 仓库名
    GITHUB_CATEGORY_ID Discussions分类名称
    GITHUB_TOKEN Github Access Token
  3. 配置完成后请redeploy!

  4. 查看是否能正确输出最新评论的json数据

stellar主题修改

  1. theme/source/js/services/ 下新建 giscus_new.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    utils.jq(() => {
    $(function () {
    const els = document.getElementsByClassName('ds-giscus');
    for (var i = 0; i < els.length; i++) {
    const el = els[i];
    const api = el.getAttribute('api');
    if (api == null) {
    continue;
    }
    const default_avatar = def.avatar;
    // layout
    utils.request(el, api, function (data) {
    const limit = el.getAttribute('limit');
    data.forEach((item, i) => {
    if (limit && i >= limit) {
    return;
    }
    comment = item.body.length > 50 ? item.body.substring(0, 50) + '...' : item.body;
    var cell = '<div class="timenode" index="' + i + '">';
    cell += '<div class="header">';
    cell += '<div class="user-info">';
    cell += '<img src=" + (item.author.avatarUrl || default_avatar) + " onerror="javascript:this.src=\\" + default_avatar + "\\";">';
    cell += '<span>' + item.author.login + '</span>';
    cell += '</div>';
    cell += '<span>' + new Date(item.createdAt).toLocaleString() + '</span>';
    cell += '</div>';
    cell += '<a class="body" href="' + item.url + '" target="_blank" rel="external nofollow noopener noreferrer">';
    cell += comment;
    cell += '</a>';
    cell += '</div>';
    $(el).append(cell);
    });
    });
    }
    });
    });
  2. _config.stellar.yml主题配置中引入

    1
    2
    3
    4
    5
    data_services:
    ...
    giscus:
    js: /js/services/giscus_new.js

  3. _data/widgets.yml 中创建小组件,并在_config.stellar.yml中选择在哪里展示

    1
    2
    3
    4
    5
    6
    7
    new_comment:
    layout: timeline
    title: 最新评论
    api: https://xxx.vercel.app # 你的 vercel 函数地址
    type: giscus
    limit: 16 # 限制获取数量,这是客户端,刚刚是服务端

成果展示

Fix 使用搜索功能搜到的部分文章无法打开

我目前使用思源笔记这个笔记软件的「发布工具」插件把笔记发布到hexo
发布工具支持在yaml里放永久链接

由于永久链接是/post/id.html形式,而使用local search搜索的时候,这些文档则会打开为https://post/id.html,导致失败
所以需要对data.path进行检测,如果以’//'开头,则path字符串只取第二位到最后一位,使其能正常打开

themes\stellar\source\js\search\local-search.js进行修改

1
2
- var dataUrl = data.path;
+ var dataUrl = data.path.startsWith('//') ? data.path.slice(1) : data.path;

已提交Pull request:https://github.com/xaoxuu/hexo-theme-stellar/pull/450