--- title: 园子装修日志(2) slug: yuanzi-decorating-2 date: 2024-08-21 summary: 今天食堂又做(酸菜)鱼了呢,小氯刚刚摸的。 description: 本文记录了作者最近优化 Hugo 博客的过程,包括优化 GitHub 卡片、重构 CSS 和侧边栏等。优化包括样式、API 逻辑、错误处理等,重构 CSS 采用 SCSS 方法,导入特定页面样式。侧边栏优化了公告、目录、移动端显示和图标,使得代码结构更加整洁。 categories: ["百草园"] tags: - 博客 - 折腾 featuredImage: https://img.viento.cc/cover/yuanzi-decorating-2-cover.webp --- 各位老友们好,我是 Chlorine。继续水文,讲讲这几天摸鱼的经历。 准确来说应该是我能记得的经历,因为我记性一向不好,而且这几天的 Git commit 也异常多: ![630](https://img.viento.cc/IMG-20240821195307.avif "还没算我写文章的时候没提交的") ## 优化 GitHub 卡片 这几乎是我的每日任务了。由于 GitHub/GitLab/Codeberg 的卡片基本上是一样的,所以说一优化可以优化三次,三倍业绩,三倍快乐,~~改 bug 也是三倍快乐~~。 这次的优化很多,包括但是不限于: - 样式打磨,我的目标就是 Vercel/iOS18 的风格~ - API 逻辑改写,更多地使用 Hugo 模板 - 错误处理完善 - 使用 license 映射来改进显示 - 自动截断过长的描述 - 图标更改,采用 Simple Icons 的 GitLab/Codeberg 图标 - 去掉父元素的 `` 标签,改良整体样式和点击容错性 此外,我在之前的老朋友 Blowfish 主题那里闲逛的时候发现他们加了 Gitea 短代码,无论谁在写 Hugo shortcode,我小氯都要帮帮场子。直接加上。Gitea 和 Codeberg 的逻辑基本上一样,毕竟 Codeberg 就是基于 Gitea 的。 顺便说一句,我发现我犯了个非常执杖的错误,就是我已经用 `resources.GetRemote` 获取 API 的数据了,我居然用 JavaScript 又获取了一次。 ## refactor CSS 闲着没事去主题原型 Hugo landscape 的仓库看了看,发现恐咖兵糖大佬把 CSS 重构了一下。正好我也一直被无法正确导入 CSS 困扰,于是就动手开始 refactor 了。 我原本的文件结构大概是: ```txt . ├── css │ ├── addon.css │ ├── algolia(almost of no use) │ │ ├── algolia_dark.css │ │ └── algolia_light.css │ ├── base.css │ ├── normalize.css │ ├── tailwind.css │ └── whisper.css ├── js ... ├── json ... └── style.css ``` 其中 `style.css` 是 UnoCSS 自动构建生成的,而我的几乎所有魔改 CSS 都堆在 `addon.css` 中,看着很难受,维护起来也不方便。 重构代码时我选择了恐咖兵糖大佬使用的 SCSS 方法:在文件夹中创建 SCSS 索引文件,然后在 `css.html` 中直接用 Hugo 来解构 SCSS 得到 CSS 导入。一顿拆分重组后得到了: ```txt . ├── addon │   ├── algolia.css │   ├── fonts.css │   ├── friend.css │   ├── index.scss │   ├── others.css │   ├── twikoo.css │   └── whisper.css ├── base │   ├── base.css │   ├── index.scss │   ├── normalize.css │   └── tailwind.css ├── main.scss ├── test.txt └── uno.css ``` 此外,对于一些只在特定页面生效的 CSS 文件(例如 `whisper.css` 只在《碎语》页面生效),我们直接在页面进行导入,避免不必要的开销。 ```html {{ with resources.Get "css/addon/whisper.css" }} {{ end }} ``` ## 侧边栏优化 在我看来,侧边栏是个相当重要的页面元素。我在侧边栏堆了公告(Announcement)、目录(TOC)、分类(Categories)和标签(Tags)。在移动端,它们会显示在主体卡片的下方。 ### 目录 这个目录改得我几乎红温。我原本是直接采用 Hugo 的 `{{ .Page.TableOfContents }}` 模板,但是其样式令人一言难尽。而且可能是因为 Swup 的原因,目录是没办法随着文章同步更新的。于是,在深思熟虑后,我决定暂时将其去掉。 > 《fix bug by removing the feature》 ### 公告 公告组件是我比较看重的东西。我采用的是在 Hugo 配置文件相应选项开启的情况下,直接读取 `content` 下的 `announcement.md` 进行展示。其功能比较完善,但是样式看起来并不好看。 我去查了些资料,找到了一个名为 prose 的布局,经过实验看起来还不错。所以就改成了这样: ```html
{{ $announcement := .Site.GetPage "announcement" }} {{ with $announcement }}
{{ .Content | markdownify }}
{{ end }}
``` ### 移动端隐藏组件 我感觉,移动端很少有人会去专门翻最下面的 categories 和 tags,所以我干脆直接把它们 `hidden md:block` 了。这样最下面就是 profile 和 announcement 了。 ### 图标 从页面的元素选择上,各位老友应该可以看出,我非常喜欢 UnoCSS 的矢量图标,尤其是 IBM 的 Carbon Icons 系列。 所以我打算给侧边栏的组件加图标。这个不算难,一个 `flex` 布局,再把图标和标题套在一起就可以了。 ```html
Categories
``` 加个边距看上去好看。 我用的图标分别是: ```html ``` ### partial 化 我原本的组件样式大部分是写在 `sidebar.html` 那里的。但是这样让 `sidebar.html` 看起来很不整洁,所以我把大部分的代码都移动到了相应的部分代码(partial)中。 ```html {{/* sidebar.html */}} ``` 可以看到基本上是一个模子刻出来的,形成可复用打法了属于。 ### 折叠展开 此外还写了个折叠展开的代码。但是感觉现在的 tags 和 categories 都不是很长,因此就没真正加上。 ## Hello,109chan > 《hello 宇宙最新力作》 ### 前言 熟悉博客圈的老友应该知道一个著名的工具:[TianliGPT](https://postsummary.zhheo.com/)。这个工具来自洪哥([张洪 Heo](https://blog.zhheo.com/))和 Tianli,是个自动生成博客文章 AI 摘要的工具。对于希望在听故事之前简单了解其脉络的老友来说是个很好的补益。 问题是:这个工具收费。虽然不贵,但是以小氯的节俭程度,还是不太舍得花这个钱的。 ~~那你买域名的时候怎么一点也不节俭啊喂!~~ 于是我就开始想替代方法。很巧,在之前写 Java 大作业的时候,我们有一个 feature request 就是 AI summary(用大模型的 API 生成新闻摘要)。虽然小氯没用过 API,但这个部分的思路大概还是很清晰的。最后实现得非常好,除了学校给的 API SDK 居然不能用,必须 HTTP,害得我和热心的答疑大佬调了半个下午。 于是我想按照这个思路做一个 AI 摘要。不过,我不太熟悉怎么在 Hugo 里面用数据库,而且我的 API 只有几千万 token 的额度,我比较担心用完(~~你确定你能写这么多?~~)。 于是我又想到了薅 CloudFlare 的羊毛。用 Workers 做 JavaScript 运行时,D1 做数据持久化,Workers AI 做摘要。这个免费额度是绝对够的,唯一的问题是我不会。 穷途末路之下,我想到了我的好伙伴:Quail。 各位老友应该都知道,我的 newsletter 是通过 [Quail](https://quail.ink) 实现的,而 Quail 为每位创作者都免费提供 AI 摘要生成功能。这个摘要直接写在 Markdown 源文件的 YAML front matter 里面,是完全静态的,既不怕丢,也不用执行复杂的 API 请求和数据库调用。 那么,就是你了。 ### 设计 由于只有 `content/posts` 中的页面需要加摘要,所以我们直接改动相应的 `single.html` 即可。位置我选择在封面图和正文之间。 先用 AI 搓个形: ```html
AI 摘要
``` 然后我简单修了下,大概就是这样了: ```html
AI 摘要
109酱
``` 移动端的点击放大我关掉了,因为看起来不太舒服。高斯模糊的手艺是跟 GPT 学的,本来想用 `var(--primary)` (就是我的博客那个一直在变化的主题色),但是不知道为什么没成功。 使用 `description` 字段可以保证其尽量都是 AI 摘要,`summary` 字段我比较喜欢用来扯淡。难绷的是 Quail 的标准 AI 摘要键是 `summary`,造成我需要手动改一下。已经和作者[歌词经理](https://quail.ink/lyric)反馈了,作者说会想办法优化一下。 嗯,你问为什么叫 109 酱啊?就不告诉你 (/ω\) ## 更新依赖 npm 有 `package-lock.json`,pnpm 有 `pnpm-lock.yaml`,yarn 有 `yarn.lock`, Bun 有 `bun.lockb`,这充分说明了对于 JavaScript 包,锁定版本有多么重要。我曾经试着直接对 `theme/efimero` 的依赖进行更新,结果自然是必遭严惩,样式全都乱了。 最近闲着没事去 UnoCSS 的[官网](https://unocss.dev)的官网看了下,发现已经到 `0.62` 了,而我的依赖还是 `0.60` 左右。由于我非常喜欢 UnoCSS,并且确信自己会一直使用,于是我想着更新一下。 直接删除 `node_modules` 和 `bun.lockb`,然后把 `package.json` 的版本全改成 `latest`,直接一手 `bun i` 更新。 然后构建,不出意料出了很多错误: ```txt Failed to load custom icon "copy" in "carbon": TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "file:///Users/chlorine/Dev/Hugo/themes/efimero/node_modules/@iconify-json/carbon/icons.json" needs an import attribute of "type: json" at validateAttributes (node:internal/modules/esm/assert:88:15) at defaultLoad (node:internal/modules/esm/load:133:3) at async nextLoad (node:internal/modules/esm/hooks:746:22) at async nextLoad (node:internal/modules/esm/hooks:746:22) at async nextLoad (node:internal/modules/esm/hooks:746:22) at async Hooks.load (node:internal/modules/esm/hooks:383:20) at async handleMessage (node:internal/modules/esm/worker:199:18) { code: 'ERR_IMPORT_ATTRIBUTE_MISSING' } ``` 看来是缺少一个导入类型。在询问 GPT 后,得知改动 `uno.config.ts` 中的导入部分为动态导入即可: ```ts import { defineConfig } from "unocss"; import { presetUno } from "unocss"; import { presetIcons } from "unocss"; import { presetAttributify, presetTypography } from "unocss"; import presetLegacyCompat from '@unocss/preset-legacy-compat'; import carbonIcons from '@iconify-json/carbon/icons.json'; import mdiIcons from '@iconify-json/mdi/icons.json'; export default defineConfig({ presets: [ presetAttributify(), presetUno(), presetTypography(), presetIcons({ collections: { carbon: () => carbonIcons, mdi: () => mdiIcons, }, scale: 1.2, warn: true, }), presetLegacyCompat({ commaStyleColorFunction: true, }) ], // ... }); ``` ## 结语 除此之外还有一堆优化,我们就不展开说了,像什么优化 Algolia Docsearch 样式之类的。静态博主都是装修爱好者,折腾就完了,把园子装修得漂漂亮亮的。 明天我考~~磕墓三~~科目三,考完之后我就要着手二次备案了。