KR1
实现博客侧边栏类别、categories、tags等文章功能配置
· 观察记录 1 - 初始化搭建 | 2025.12.12
没错我又回来搭建博客了 (从去年12月弄到今年www)!本来5月份的时候用hexo-butterfly搭建了一个,但是后面接着又是高考然后又是开学,所以理所当然地忘记了()。不过没关系,现在又想起来这码事情了!(其实是敲了几天代码心血来潮想写写博客记录一下)
这次换了一个更中意的Stellar 主题,然后又得从头开始配置config文件,搞半天有些图标还没办法正常显示,属实是烦得飞起。
明天要考四级了,一定要成功啊啊啊!
· 观察记录 2 - 图标、背景、杂七杂八的小功能 | 2025.12.14
昨天考完了四级,理所当然地鸽子掉了一天(,不过还是有试着做了点东西,所以干脆合并到今天一起来写了!
- 首先是修好了网站图标显示异常的问题 -
_config.stellar.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 menubar: columns: 5 items: - id: blog theme: '#1BCDFC' icon: solar:documents-bold-duotone title: 博客 url: / - id: gaming theme: '#FA6400' icon: solar:gamepad-bold title: 游戏记录 url: /gaming/
一开始我从Yesicon 兴冲冲地引入solar:gamepad-bold, cib:visual-studio-code 这一类标签的时候,本来盼着会让自己地导航栏变得高级几分,结果不仅没有显示图标,反而变成了一坨文字挤在那小小的格子里,甚是丑陋。
正当我百思不得其解的时候,我发现注释里面有写可以定义在icons.yml 文件中 ,于是我调用万能的资源管理器的搜索功能,发现这玩意的目录是/themes/stellar/_data/icons.yml :
/themes/stellar/_data/icons.yml 1 2 3 4 5 6 7 8 9 solar:documents-bold-duotone: ... solar:chat-square-like-bold-duotone: solar:planet-bold-duotone: solar:notebook-bookmark-bold-duotone: ...
虽然前面的小技巧我是一点都没看懂,不过我至少知道怎么从外部导入svg图标了,其中xxx:xxx 是图标引用的名字,虽然怎么设置都可以,但是还是按照人家给的标准名称来写会好一点。冒号后面的东西就复制粘贴网站上有"<svg>"的那一坨东西就ok了。
不过需要注意的是,据我观察,侧边栏的导航图标都是32*32px的 ,而侧边栏Footer的图标好像没有一个确切的大小,我就把尺寸计量换成em了,设定width和height都是1.2em。
有了这些,我就美美地给侧边栏加上了游戏、学习、开发、友链 这几个选项卡(虽然我还不会用),Footer也美美加上了RSS、Github、网易云还有B站 的链接~
Ψ( ̄∀ ̄)Ψ
- 接下来就是背景图片还有网站图标的配置 -
对于创造力低下的瓦塔西,找图或是画图什么的是绝对不可能的捏,于是我非常自然地用上了豆包sensei。
(顺便吐槽一句,Gemini是真逆天啊,我发一个对话不仅输出异常,还把我用Nano Banana的次数用掉了!)
(╯▔皿▔)╯
话不多说,上图!
背景图-阴雨天的温馨小书房
网站の图标
网站图标的设置并不难,我直接用在线工具把直接png转svg就完成了,问题在于这个网站的背景配置 。
配置文件里是这么写的:
_config.stellar.yml 1 2 3 4 5 6 7 style: ... site: background-image: blur-px: 100px blur-bg: var(--bg-a75) blur-sat: 300 %
我把background-image换成了我的图片以后,我发现这个背景被糊上了一层贼厚的模糊 ,而且这几个blur的参数我完全不会配置/(ㄒoㄒ)/~~
最后我在Deepseek的帮助下也是明白了,
blur-px所谓的模糊半径可以理解成模糊的厚度,我设置成了2px,有种毛玻璃的感觉
blur-bg里这个var(–bg-a75)的颜色其实是一个预先配置好的变量,在themes/stellar/source/css/_defines/theme_base.styl 有定义
(真是找死我了(╯▔皿▔)╯);
最后这个blur-sat是饱和度,虽然我感觉改动了以后的效果不是很明显,我还是按照Deepseek推荐的150%来改了 。
值得注意的是,Stellar文档里说了:
此功能在 1.26.4 中支持,可以设置:纯色/渐变色/图片作为背景。未完全适配,慎用!
事实证明确实没有完全适配,至少手机上是这样的,我想看后续能不能手动给移动端做个自适应(不知道得多久了ww,技术力太低了呜呜呜)
- 字体设置 -
你知道的,我一直是霞鹜文楷的忠实粉丝 ,所以我的博客怎么可以没有它!
在这之前,我一直采取的是把字体下到本地在通过不知道什么方式搞到页面上的(我记不得了)。这一回我懒了,干脆直接用霞鹜文楷的CDN了。
至于怎么用呢:
_config.stellar.yml或_config.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 inject: head: - ... - <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/lxgw-wenkai-screen-webfont/1.7.0/style.min.css" media="all" /> bottom: - ... style: font-family: body: '"LXGW WenKai Screen", ...(省略)' code: '"JetBrains Mono", ...(省略)' codeblock: '"JetBrains Mono", ...(省略)'
只要像上面这样,把字体的css文件通过inject导入到页面就可以用在style.font-family用它了。顺带一提,我code部分我强推JetBrains Mono ,看起来真的很不错。
还有一点,关于这个inject,我搜出来的是head导入的是在线/本地的.css文件 ,bottom导入的是在线/本地的.js文件 ,自定义js文件后面可能会用得到(当然现在是一点不会)。
- 其他杂七杂八的配置 -
我从这位大大的blog中薅下来了文章前显示字数、侧边欢迎语、页面底部字数统计 这些功能,虽然这里也有访问量和运行时间统计,不过我暂时没去看busuanzi的统计,所以就只从下面这位大大的教程里扒了运行时间统计 的代码
所有的操作都在里面写得很清楚啦,这里就不复制粘贴了()
- 今日总结 -
不知不觉就弄了不少东西,码字也从23点码到了25时(bushi),总之感觉收获非常丰富,这个博客也是越来越有模有样了
闲暇之余,我去申请了一个萌国ICP备案 ,顺便看了看其他的民间备案,发现有些备案的站长还会时不时看看网站的更新情况,跟申请者们强调
希望我能坚持下去吧。
晚安!
观察记录 3 | 2025.12.15
今天和同学到图书馆和数学大战三百回合,落败而归,于是晚上继续回来装修这个博客~
更新时间信息常驻
首先是找到了updated可见性的设置位置,那么我就可以通过修改css样式让它常驻啦~
themes\stellar\source\css\_components\partial\bread-nav.styl 1 2 3 4 5 6 7 8 9 div#post-meta span .sep :before content : '|' span .updated visibility : visible // 修改:这里默认是hidden,我改成了visible以实现默认显示 &:hover div#post-meta span .updated visibility : visible
可以显示更新时间啦~
链接卡片API
参考这个教程弄了一个api,不过有几点要注意的:
在Vercel上填写这个的这个HOSTS的Value中,第三个值要填写Vercel项目解析的域名。比如我按照教程fork并在Vercel上部署后,域名解析是api.abc.top,那么第三个值就填api.abc.top
Key
Value
HOSTS
['', 'localhost', '部署API的地方所解析的域名']
原文:
使用方法示例: 1 2 3 https://your-domain/api/v1?url=https://xaoxuu.com (意思是可以把your-domain换成你刚刚配置的东西然后输入到浏览器里) > 例如: https://site-info-api.vercel.app/api/v1?url=https://xaoxuu.com
如果需要配置到 Stellar 主题中,写法就是: _config.stellar.yml 1 2 siteinfo: api: https://your-domain/api/v1?url=${href}
事实上,按照 your-domain/api/v1?url=${href} 这个写法是没法获取到网站信息的,需要把其中的"$"删去,即your-domain/api/v1?url={href}才能用。
Mathjax支持
学了一天数学想记录一下自己的收获,让后就非常不幸地在LaTex公式的显示上载跟头了。
我一开始调用latex公式的时候,渲染出来的字体小得可怜(比正文的字体还小)。我百思不得其解,于是便去求助了Deepseek,不过这一回D老师似乎没有帮上太多忙,我按照生成的css代码放到themes\stellar\source_custom.styl中,但是没有什么效果。
于是我不得已代开F12开发者工具开始查看渲染latex公式的标签元素,发现是这么一个结构
1 2 3 4 5 <mjx-container class ="MathJax" jax ="SVG" display ="true" > <svg > ... </svg > </mjx-container >
根据我的惊世智慧(bushi)判断,<svg>标签渲染的是生成的数学公式,里面存储的都是矢量图的数据,我应该是没法改动的。那么我的视线就自然落到了这个<mjx-container>上,它指定了一个名叫MathJax的class。根据我看了Deepseek生成的那么多代码,这个class应该就是在css文件中用来指定样式的一个标签。那么我只要在themes\stellar\source_custom.styl中重新指定它的字体大小应该就可以了(事实上Deepseek也是这个思路,不过我当时没看懂代码里干了什么)
themes\stellar\source\_custom.styl 1 2 3 4 5 6 7 8 9 10 11 12 .MathJax { font-size : 2.0em !important ; line-height : 1.0 // 顾名思义行内高度,我改这个时想缩短公式块与文字段落之间的高度空隙 margin : 0.5em // 我搜了一下好像是元素的外边框的宽度参数 } .mjx-container [jax="SVG" ] [display="true" ] { margin : 0.5em ; }
这样子改就可以实现我想要的字体大小啦。
背景图片聚焦中心
这一段得感谢D老师,还有一个非常重要的功能:VSCode的查找功能(Ctrl+Shift+F) 这个功能帮我快速找到了背景的css代码,节省了成吨的时间orz。
themes\stellar\source\css\_components\main.styl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 body>.sitebg ... background-position : center center background-repeat : no-repeat background-size : cover background-attachment : fixed ... @media screen and (max-width : $device-mobile-max) background-attachment: scroll
有了这个设置,背景图就能在任意设备居中显示啦~
小bug修复:页脚长度溢出
这个bug在手机上比较明显,经过F12排查,我发现是之前加的那个时间长统计的玩意把页脚那个元素拉长了:
themes\stellar\source\css\_custom.styl 1 2 3 4 5 6 7 8 9 10 11 12 13 .post-count { scrollbar-width : none; color : var (--text-p2); } .totalcount { color : var (--text-p2); } .page-footer { text-align : center; margin : 0 auto; width : auto; }
小总结
今天又是翻代码的一天qwq,不过对stylus还有html这些前端的东西开始有一点了解了,也实现了一些功能,开心~
下一阶段就是文件目录管理和站内分类导航了!
晚安!
观察记录 4 主页卡片日期样式 | 2025.12.16
很好,目前暂时没有进入下一阶段!
昨晚上传代码以后发现网站背景模糊失效了,页面连主题自己定义的css全局变量都读取不了,经过我用git逐个检查后发现是Mathjax样式那几行代码被我注释掉导致的:
themes\stellar\source\_custom.styl 1 2 3 4 5 6 7 8 9 10 11 .MathJax { font-size : 2.0em !important ; line-height : 1.0 // 顾名思义行内高度,我改这个时想缩短公式块与文字段落之间的高度空隙 margin : 0.5em // 我搜了一下好像是元素的外边框的宽度参数 } .mjx-container [jax="SVG" ] [display="true" ] { margin : 0.5em ; }
原因我不是很清楚,总之解决了问题就好()
今天搓的都是些一些小小的东西,直接进入正题吧!
首页卡片添加日期信息
为了实现这个功能,真是把我累得半死不活qwq
我主要参考了之前往文章banner添加字数统计的那段代码:
themes\stellar\layout\_partial\main\navbar\article_banner.ejs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 3.left.bottom el += partial('dateinfo') //新增:字数显示|阅读时长显示 el += '<div class="flex-row" id="page-words"><span style="padding: 4px;">本文:' + wordcount(page.content) + '字</span><span class="sep updated" style="padding: 4px;"></span><span class="text updated" style="padding: 4px;">阅读时长:' + min2read(page.content) + '分</span></div>'; //新增:标签显示 if (page.layout == "post" && page.tags && page.tags.length > 0) { el += '<div class="flex-row" id="tag">'; // 将标签容器的创建移动到条件内部 el += ' <span> 标签:</span>'; el += list_categories(page.tags, { class: "cap breadcrumb", show_count: false, separator: ' ', style: "none" }); el += ' </div>'; }
由于我没学过ejs,也没学过css、html,所以我只能揣测这里在干什么了。因为我只需要展示文字信息,还不用管标签,所以我就只看 新增:字数显示|阅读时长显示 这一部分,然后参考banner本来就有的显示日期信息的代码来写了。
根据我的观察和理解,很显然,在ejs文件中网页的html信息是通过el这个东西不断拼接字符形成的,那么我只用仿照在banner显示日期信息的代码就可以了。
themes\stellar\layout\_partial\main\navbar\dateinfo.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 function layoutDiv() { var el = '' el += `<div class="flex-row" id="post-meta">` // 注意看这里,这里给div绑定了一个"post-meta"的id ... else { const author = theme.authors ? (theme.authors[page.author] || theme.default_author) : null if (author) { el += `<a class="author" href="${pretty_url(author.path)}">${author.name}</a>` el += `<span class="sep"></span>` } // 发布日期 el += `<span class="text created">` if (!author) { el += `${__("meta.created") + __("symbol.colon")}` } el += `<time datetime="${date_xml(page.date)}">${date(page.date, config.date_format)}</time>` el += `</span>` // 更新日期 el += `<span class="sep updated"></span>` el += `<span class="text updated">` el += `${__("meta.updated") + __("symbol.colon")}` el += `<time datetime="${date_xml(page.updated)}">${date(page.updated, config.date_format)}</time>` el += `</span>` } } ...
这里面写得也挺清楚的了,我只用把发布日期和更新日期这两块弄到首页展示的那个位置就行了。经过Ctrl+Shift+F搜索,我定位到了这里:
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 function div_photo() { ... if (position.length > 0) { el += '<div class="cover-info" position="' + position + '"'; if (obj.topic) { el += '<div class="text topic">' + obj.topic + '</div>'; } if (obj.headline) { el += '<div class="text headline">' + obj.headline + '</div>'; } if (obj.caption) { el += '<div class="text caption">' + obj.caption + '</div>'; } ... }
这里这几个if语句挺明显的了,其中的headline、caption就是首页那个卡片上的标题元素,那我只用仿照前面在这几个if语句后面添加<div>元素就可以了:
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 const poster = post.poster; var obj = { image: post.cover }; if (poster) { obj.headline = poster.headline; obj.topic = poster.topic; obj.caption = poster.caption; obj.color = poster.color; // 添加: 获取文章日期和更新时间 obj.date = post.date; obj.updated = post.updated; } ... // 添加:首页卡片日期显示 if (obj.date) { el += '<div class="text datecard" id="post-meta">'; // 这个"post-meta"的id记得加上,不然不会显示成相对时间 el += `<span class="text created">${__("meta.created") + __("symbol.colon")}`; el += `<time datetime="${date_xml(obj.date)}">${date(obj.date, config.date_format)}</time>` el += `</span>`; // 如果文章填写updated字段,就在添加到后面 if (obj.updated) { el += `<span class="sep updated"></span>`; el += `<span class="text created">${__("meta.updated") + __("symbol.colon")}`; el += `<time datetime="${date_xml(obj.updated)}">${date(obj.updated, config.date_format)}</time>`; el += `</span>`; } el += `</div>`; }
顺带一提,在填了caption这个东西之后会换另外一种展示模式,这里顺便一起加上:
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 ... // meta el += '<div class="meta cap">'; el += '<span class="cap" id="post-meta">'; el += icon('default:calendar') // time // 添加:这里原来有一个显示组件,我把它给覆写了 el += `<span class="text created">${__("meta.created") + __("symbol.colon")}</span>`; el += `<time datetime="${date_xml(obj.date)}">${date(obj.date, config.date_format)}</time>`; el += `<span class="sep updated"></span>`; el += `<span class="text created">${__("meta.updated") + __("symbol.colon")}</span>`; el += `<time datetime="${date_xml(obj.updated)}">${date(obj.updated, config.date_format)}</time>`; el += '</span>'; // cat ...
然后在控制这些元素的styl文件添加相应的样式:
themes\stellar\source\css\_components\list.styl 1 2 3 4 5 6 7 8 .post-list .post-card .post .photo .cover .cover-info ... .datecard font-size : $fs -13 ...
但是在最开始的时候,日期确实是显示了,但是并没有变成相对日期(如前面的图片所示),我也是百思不得其解,气得我直接回去做英语U校园作业去了(bushi)。在我配合Github Copilot一阵摸索过后,我发现 原来在dateinfo.ejs中,存放日期信息的div标签中,有一个id=“post-meta”(在浏览器F12里能看到是<div class=“flex-row” id=“post-meta”>),这个玩意加到我定义的那个div标签里就能显示相对日期了 。
codeblock:true 至于为什么,想了解一下的就点开这里吧
这个相对日期的实现,其实是通过js脚本来实现而非通过css控制的。所以就算是原来的代码,把id="postmeta"去掉以后,也只会显示绝对日期而非相对日期。 而相对日期的计算,是通过 themes\stellar\source\js\main.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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 const util = { diffDate : (d, more = false ) => { const dateNow = new Date () const datePost = new Date (d) const dateDiff = dateNow.getTime () - datePost.getTime () const minute = 1000 * 60 const hour = minute * 60 const day = hour * 24 let result if (more) { const dayCount = dateDiff / day const hourCount = dateDiff / hour const minuteCount = dateDiff / minute if (dayCount > 14 ) { result = null } else if (dayCount >= 1 ) { result = parseInt (dayCount) + ' ' + ctx.date_suffix .day } else if (hourCount >= 1 ) { result = parseInt (hourCount) + ' ' + ctx.date_suffix .hour } else if (minuteCount >= 1 ) { result = parseInt (minuteCount) + ' ' + ctx.date_suffix .min } else { result = ctx.date_suffix .just } } else { result = parseInt (dateDiff / day) } return result }, ... relativeDate : (selector ) => { selector.forEach (item => { const $this = item const timeVal = $this.getAttribute ('datetime' ) let relativeValue = util.diffDate (timeVal, true ) if (relativeValue) { $this.innerText = relativeValue } }) }, ... } init.toc () init.sidebar () init.relativeDate (document .querySelectorAll ('#post-meta time' )) init.registerTabsTag () init.canonicalCheck ()
具体的计算过程看上面那个函数体就行了,重点在于最后这里的init步骤,document.querySelectorAll(‘#post-meta time’)就是搜索标签的属性,这里出现了#post-meta和time,也就是说id带有post-meta的元素下面的<time>标签 (这是我自己的理解,不一定对)都会被这里捕获然后送到relativeDate()获取相对日期值。所以给自定义的那个div加上id="post-meta"就没问题啦~
最后这里算是我的强迫症又犯了,我把这个卡片上的分割符号也换成"|",跟文章顶部的banner那里统一:
themes\stellar\source\css\_custom.styl 1 2 3 4 5 .cap span .sep :before ,.datecard span .sep :before { content : "|" }
其他小变化
首先是我把文章内banner的那层模糊蒙版设置成常开了(本来是鼠标悬停才会显示的),同时在Deepseek的指点下添加了文字阴影(本来是打算做文字根据背景颜色进行反色处理的),这样文字显示得会更清楚一些
themes\stellar\source\css\_components\partial\article-banner.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 .article .banner .bg+.content --blur-bg : rgba (black, 0 ) --blur-px : 1em --blur-sat : 100% --blur-height-top : 6rem --blur-height-bottom : 7rem --blur-opacity : 0 &:hover --blur-bg : rgba (black, 0.1 ) --blur-sat : 150% --blur-height-top : 6rem --blur-height-bottom : 7rem --blur-opacity : 1 .bg+.content --blur-bg : rgba (black, 0.1 ) --blur-px : 1em --blur-sat : 150% --blur-height-top : 6rem --blur-height-bottom : 7rem --blur-opacity : 1
themes\stellar\source\_custom.styl 1 2 3 4 5 6 7 8 9 .banner .content .text .title span ,.banner .content .breadcrumb ,.banner .content #post-meta ,.banner .content #page-words ,.banner .content #tag { mix-blend-mode : difference; text-shadow : 0 1px 3px rgba (0 ,0 ,0 ,0.5 ); }
今天差不多就到这了,晚安!