趁着开学事情不多,好好折腾了一下这个新玩具主题,简直有点到爱不释手的地步了。记录一下魔改的过程,以供自鉴;如果能帮到有类似需求的朋友们就更好啦!
你好 Stellar!
博客组织方式之我思
众所周知 Stellar 最吸引人的特性之一是强大的 Wiki 文档系统,但一番操作发现并不是所有的文章都适合用 Wiki 进行组织。
- 向 Wiki 项目中添加文章的过程有点繁琐,得改目录树。
- Wiki 项目中的文章居然
不在主页显示 !即是说假如我的某篇得意之作被收录在 Wiki 项目里,我就无法在主页展示出来;这要求我必须在我的强迫症和虚荣心中舍彼取此。当然有一个方法是项目wiki/[project]
里收录一篇,再复制一篇到主页_post
,但这个解法实在是太丑陋。 - 某些主题不明确的文章不适合收到一个集子里。本来打算是专门弄一个「其他」项目,但仔细想想假以时日这个「其他」一定会膨胀到难以忽视。
我仔细审视了一下我的博客内容,大概分成四类。

首先 A 型内容很适合做成 Wiki 项目。一方面它们已经成型,后续的增补内容很少;另一方面它们大多数是作为有机整体的课程笔记系列,不太有机会需要单拎一篇出来放到主页。
而 B 型内容多数是散乱的课程笔记/自学记录,质量良莠不齐,显然我想要展示一部分,隐藏一部分;但被隐藏的内容并不代表没有价值,我还是需要挂在博客上供我自己参考回顾,只是我个人并不是特别满意罢了。
C 型内容是我的读书/观影/游戏记录,以时间为经连缀起我的精神生活碎片,显然是需要不断增补更新的。并且这其中有一些认真写的书评/影评/游戏评,是我想放在主页上展示的。
最后的 D 型内容是我日常的一些文字随笔,没有特定主题,也无需时间串联,整个形式是十分随意的,但这一部分却是我很想展示在主页的内容。
哇!简直乱糟糟!不仅每种内容的组织形式不同,结构完整度不同,我想要展示的欲望也不同!而当中仅仅只有需求 A 是原生 Stellar 可以解决的!如果谁能想到办法四个需求一次满足的话,那 TA 一定是
我们需要「专栏」!
还好!Stellar 提供了一种有别于 Wiki 项目的简化组织形式 —— 专栏,这让我的大业又推进了一步。
简而言之,「专栏」就是没有目录树的 Wiki 项目,其单纯的以时间为索引松散的连缀一系列指定主题的文章。但这同时引入了一个新问题:专栏没有 index 页,每次点进去默认显示的都是最新的文章,而我想要的是一个类似目录或者扉页的东西。
Wiki 项目能够很容易的实现这一点,只要建一个 index 并把它指定为目录树的开头就行。真是成也目录树,败也目录树!
为了解决这个问题,我定义了一个新的 front-matter 字段:topic_pin
:
1 | for (let tid of Object.keys(topic.tree)) { |
在专栏中创建一个 index 页,再在 front-matter 中设置 topic_pin: true
就大功告成啦!
……把思路逆转过来!
试着把 B 型内容和 C 型内容用改良后的专栏来组织,效果很好!在此期间还发现一件有趣的事:由于专栏不要求 markdown 文件存储在 _post
之外,收录不收录到专栏并不影响文章本身在主页上的显示。
之前研究 Wiki 项目产生了惯性思维,一直在想怎样把项目内的亮点文章挪到主页来显示;没想到专栏的这个特性使得需求逆转了:现在需要考虑的是
等等!这不是我在老博客中使用过的 hexo-hide-posts 插件吗!
激动的配置好这个插件,隐藏文章 —— 果然没我想象的那么简单。Stellar 的 topic 并不是一个常规的 generator,不能直接写在白名单里;这就是说当我在主页隐藏某个文章的同时,这个文章同时也在专栏中被隐藏了。
好嘛!到头来还是逆转回去了。异议阿里!
只好想了个折衷的办法,虽然逆转再逆转的思路确实不太优雅,但实现起来却很简洁(毕竟插件把大部分逻辑都抽象好了,不用白不用):
1 | hexo.extend.filter.register('before_generate', function() { |
这个 handler 会在 hexo-hide-posts 作用之前收集所有被 hidden: true
标记的文章,并在之后 merge_posts.js
脚本收集专栏文章的时候返还 hiddenTopicPosts
中对应专栏的隐藏文章。天哪说起来都好绕。
最终效果见我的专栏,你会发现不是所有的专栏文章都会显示在主页上喔。是不是很不错!
静态 timeline 标签组件化
之前提到,C 型内容是根据时间组织的,而 Stellar 正好提供了「时间线」组件,非常契合我的需求。我想在 C 型内容首页的右侧边栏挂上时间线,每次读完一本新书,打完一部游戏,就能往上串一条新的经历,多有满足感!
但事情比我想象中的棘手。仔细阅读完教程后我发现,「时间线」实际上有两种:
- 静态时间线:放在正文部分,是一个
{% timeline %}
标签,内容是写死在 markdown 里的。 - 动态时间线:这才是侧边栏组件,需要配置 API 从其他地方提取动态数据;但这不是我想要的。
我的需求是把静态时间线配置到侧边栏组件上,这一点原生 Stellar 并不支持。
又注意到侧边栏组件中有一个叫 markdown 的,非常的灵活,支持在侧边栏显示任意形式的 markdown 语法文本。尝试将 {% timeline %}
标签写进去,果然不渲染。
那么我们让它渲染不就行了嘛!照猫画虎根据 markdown 组件的逻辑扩展了 timeline 组件,新增 content
字段,并且以有无 api
字段决定是动态还是静态时间线。
核心修改逻辑
1 | if (item.api) { |
还得小修一下 themes\stellar\source\css\_components\widgets\timeline.styl
使得静态时间线组件的标题与内容排列更加紧凑,比较繁琐,故按下不表。
你可以去探索页,书/影/游戏评主页的右侧边栏看到实现的效果。是不是挺像那么回事的?
Giscus 评论区主题自定义
之前的老博客用的是早已停止开源的 Valine,听说还有隐私泄露的风险,所以趁着升级博客把评论系统也给换一换(之前的评论都要无了 555)。
Giscus 基于 Github Discussion 来做映射简直是一个天才般的想法,配置起来也无比的简单,就是可能对没有 Github 账号的朋友不太友好。
除此之外还有一个让我强迫症发作的点在于 Giscus 组件是一个 iframe,不受我博客的 CSS 样式管辖,这就造成我没法在评论区用上美丽的落霞孤鹜字体。
研究了一下,成功用 Giscus 提供的自定义主题接口解决了,顺便还调整了一下边框样式,加了夜间模式。有需要的朋友可以在 这里 自取我的样式文件,直接托管到你自己的网站上再修改 Giscus 的 data-theme
字段就好啦!记得 url 不要加 www 前缀,不然会 CORS。
其他想要做的事
计划在学期内结束。
计划顺序:D => C => B => A