这不是 git log,是一份有点像日记的迭代记录。


2026-07

feat主题系统扩充四套配色,顺手修了几个交互细节
2026-07-14

去看了眼 herdr.dev,一个终端 AI agent 多路复用器的官网——它走的是"终端配色文化"路线,Catppuccin、Tokyo Night、Dracula、Nord、Gruvbox 随便切,跟这个博客本来的 IDE 分屏、终端 prompt 调性很搭。抄了个作业,加了 Dracula、Nord、Tokyo Night(暗色)和 Gruvbox Light(亮色),主题菜单从 3 个选项变成 7 个。

切主题的时候顺手修了几个之前没注意到的小毛刺:

  1. 底部状态栏那个 [latte] 按钮没有固定宽度,主题名从 latte 切到 gruvbox light 按钮跟着变宽,popover 的锚点也跟着跳。按最长的主题名(gruvbox light,13 个字符)算出一个固定的 ch 宽度焊死。
  2. 顶部导航 tab 选中态原来用 ::before { content: '| ' } 插一个竖线字符当指示器,只有选中的 tab 会多出这两个字符宽度,切页面时整排 tab 跟着挪位置。改成绝对定位的一条 2px 竖线叠在 tab 上,不参与排版,只是非选中态时透明——彻底不占布局空间,而不是"占位但隐身"。
  3. 主题菜单选中一个主题后没有自动收起,点开一次要再点别处才会关掉;补了 setOpen(false)。
  4. 有几率一进页面主题菜单就是展开状态(没点过按钮);给 popover 挂载后补了一次显式 hidePopover() 兜底。
javascript
  之前:  0:主页  1:文章    ← 切到"文章",因为多了"| ",后面的 tab 全部右移
  之后:  0:主页┃ 1:文章    ← 竖线叠在色块上,不吃版面,其余 tab 纹丝不动
featToken 用量页大改:排行换成调用趋势,图表全联动
2026-07-14

之前「按模型 top5」的排行是按 6 个月 token 总量排的,结果 gpt-5.2 只打了 851 次请求就冲到第一——单次平均 7 万多 token,明显是几次长上下文批处理,不是日常用量。换成按调用次数排序,Claude 系列立刻回到该在的位置。

顺手把整个用量维度从「当天按小时」放大到「近30天按天」:上游 /api/data/self 本来就限制单次最多查30天,原来「近1天 + 6×30天」拼7次请求的写法直接简化成1次。

新增一张手写 SVG 折线图看多模型趋势(中点二次贝塞尔平滑,没上任何图表库),和模型调用占比环形图,两个图表共用一份图例。图例、折线、饼图、原来的柱状图全部联动——hover 任意一处,其他地方同步高亮同一个模型,饼图中心文字也会切换成当前 hover 模型的次数和占比。

javascript
  图例 ●claude-sonnet-5 ← hover
         │
         ├─→ 柱状图对应色块变亮,其余变暗
         ├─→ 折线图对应曲线加粗,其余变暗
         └─→ 饼图对应扇区加粗,中心文字切换成该模型数据
feat共享元素转场:列表标题「飞」进编辑器 tab
2026-07-08

点开一篇文章,那行标题不再是凭空消失重来——它会平滑地移动、缩放到左上角的编辑器 tab 位置。把「打开一个文件」这件事讲清楚了。

用 React <ViewTransition> 给列表项标题和详情页标题挂上同一个 name,浏览器负责 morph。非点击项 exit="none",不跟着乱动,只随页面淡出。

javascript
  /blog                          blog/headless-browser…
  ┌───────────────────────┐      ┌───────────────────────┐
  │ > 无头浏览器去点按钮   │  →   │ 无头浏览器去点按钮  0 │ ← tab
  │ > 环形缓冲区           │      │───────────────────────│
  │ > 计算机网络应用层     │      │ 那行标题飞了上来       │
  └───────────────────────┘      └───────────────────────┘

折腾点:一开始用手写 CSS view-transition-name,结果 React 接管转场后不认,只剩淡入。改成显式 <ViewTransition> 边界才 morph 起来。

feat内链 hover 预览卡片 + Speculation Rules 预渲染
2026-07-08

IDE 里 hover 一个符号会弹出定义摘要。把这个隐喻搬到正文内链上:悬停站内文章链接,弹出目标文章的标题 / 摘要 / 日期·阅读时长小卡片,移开即隐藏,点进去立即消失。

同时用 Speculation Rules API 在「即将点击」时后台预渲染 /blog/*,让打开近乎瞬时。都是渐进增强,不支持的浏览器忽略。

javascript
  …详见 [环形缓冲区](/blog/ring-buffer) 那篇…
                        │ hover 140ms
                        ▼
        ┌──────────────────────────────┐
        │ 环形缓冲区                    │
        │ 无锁队列、位运算取模、Go 实现…│
        │ 2026-03-25 · 8 min read       │
        └──────────────────────────────┘
feat文章大纲:scroll-spy 高亮 + 结构 minimap 轨
2026-07-08

侧栏目录从静态列表升级成会跟着阅读位置走的大纲:左侧一条竖轨,当前读到的 section 那一段亮蓝色,像编辑器左侧的 gutter。点击平滑跳转。

用 IntersectionObserver(以视口为参照),同时兼容「桌面 pane 内滚动」和「移动窗口滚动」两种容器。

javascript
  目录
  │ 背景
  ┃ 实现思路      ← 当前 section(亮蓝)
  │ 位运算取模
  │ 性能对比
  │ 小结
feat跨页导航动画(View Transitions)
2026-07-08

切换页面时,中间内容区轻微淡入 + 上滑 4px,常驻的 Header / Footer / 桌面宠物 / 进度条纹丝不动。基于 React <ViewTransition>,只包裹路由内容区。

顺手把原来的主题圆形扩散限定到「仅主题切换」——否则每次翻页整个外壳都会被圆形擦除一遍。

javascript
  Header ──────────────  (不动)
  ┌────────────────────┐
  │  旧页 ░░░ → 新页    │  ← 只有这里淡入上滑
  └────────────────────┘
  Footer ──────────────  (不动)
feat一批现代 Web 平台能力
2026-07-08

借这次改造把几个「零 JS、纯平台」的新能力铺上:

javascript
  Popover API        底部主题下拉 → 原生 popover
                     自带 light-dismiss / Esc / 顶层渲染 / ARIA

  @starting-style    移动端菜单进出场动画,纯 CSS,删掉了
  + allow-discrete   一个从没被 import 的 headless 死组件

  animation-timeline 文章顶部滚动阅读进度条(scroll())

  field-sizing       评论框随输入自动长高

  text-wrap          标题 balance、正文 pretty,消灭孤行字
fixreduced-motion 全覆盖 + 可访问性补齐
2026-07-08

之前只有主题切换尊重 prefers-reduced-motion,其余动画照跑。这次一次性收口:

  1. 一个定向 reduce 块把所有装饰性 @keyframes(fade-up / bar-reveal / 宠物系列…)、跨页与共享 morph 全部降为瞬完终态,平滑滚动降为 auto。
  2. Tabs 补齐 tablist/tab/tabpanel 语义 + aria-selected + 左右方向键;移动菜单按钮补 aria-expanded/aria-controls。
  3. Image 默认 sizes 防布局抖动;头像 alt 从 "avatar" 改成作者名。
  4. 删掉两个从未被引用的死组件(MobileNav / ThemeSwitch)。
javascript
  @media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*) { animation: none !important }
    @keyframes fade-up { from, to { opacity: 1; transform: none } }
  }
fixUmami PV 接口防御性降级
2026-07-08

阅读量接口在上游不可用时(缺凭证、限流、token 过期)会因为在非数组上 .find 直接抛 500。改成:拿不到有效数组就返回 null,前端据此隐藏指标位,而不是刷红或误显示「0 阅读」。

javascript
  上游 OK      → { views: 1234 }   显示 "1,234 views"
  文章真 0 阅读 → { views: 0 }      显示 "0 views"
  上游挂了     → { views: null }   ← 组件隐藏,不再 500

2026-04

featKonami Code 出金彩蛋
2026-04-142f534dd

任意页面输入上上下下左右左右 BA,当前桌面宠物立即升为传说级闪光变体,触发破壳动画并弹出专属台词。

javascript
  ↑ ↑ ↓ ↓ ← → ← → B A

        ★★★★★ LEGENDARY ★★★★★
           [~~~~~]
            /\_/\
           ( ✦ ✦ )   ← 闪光变体激活
           (  ♥  )
           (*)_(*)

  > 出金了!

秘籍生效不会持久化,刷新后恢复正常概率——彩蛋猎人专属。

feat主题切换圆形扩散动画
2026-04-142f534dd

切换主题时,从底部状态栏主题按钮位置向外以圆形扩散过渡,取代瞬间变色。基于 View Transitions API,不支持的浏览器自动降级,prefers-reduced-motion 时也不触发。

css
@keyframes theme-reveal {
  from {
    clip-path: circle(0% at 95% 98%);
  }
  to {
    clip-path: circle(150% at 95% 98%);
  }
}

切换 latte → mocha → old-hope 时效果尤其明显。

featToken 图表 hover 交互 + 当前小时高亮
2026-04-142f534dd

悬停某个小时柱:浮窗显示该时段各模型 token 明细(按用量排序),其他柱半透明。当前小时列用黄色边框标注,x 轴标签同步高亮。

javascript
  hover 14:00

  ┌─ 14:00 · 42,830 tok ──────────┐
  │ ▌ claude-opus-4-5   28,100    │
  │ ▌ claude-sonnet-4   11,200    │
  │ ▌ claude-haiku-3     3,530    │
  └────────────────────────────────┘

  ...  12  13  [14]  15  16  ...
                ▲ 黄色 = 当前时刻
fixCSS 变量补全 + 动画系统统一
2026-04-142f534dd

修了两个潜伏已久的问题:

  1. --c-teal / --c-sapphire 在 Token 图表里被引用但三套主题都没有定义,颜色一直 fallback 到 currentColor。补全了 latte / mocha / old-hope 三套值。

  2. IinaTokensPage、CodeStatsWidget、TerminalPet 各自内联了几乎相同的 @keyframes。全部抽离到 css/tailwind.css,同时新增 --anim-fast/std/slow/ease 全局动画变量。

css
/* 之前:三个组件各自内联 */
@keyframes cs-bar  { ... }   /* CodeStats */
@keyframes token-bar { ... } /* Tokens */

/* 现在:统一为 */
@keyframes bar-reveal { from { clip-path: inset(0 100% 0 0) } ... }
@keyframes fade-up    { from { opacity:0; transform:translateY(4px) } ... }
@keyframes bar-grow   { from { transform: scaleY(0) } ... }
feat文章元信息:日期 / 阅读时间 / 阅读量
2026-04-13ca830cb

文章顶部加入三项信息,布局改为左右分列:左侧日期 + 阅读时间(contentlayer 构建时计算),右侧实时 PV 来自 Umami API。

javascript
2026年4月13日   5 min read              1,234 views
←──────────────────────────────────────────────────→

同期修了 Umami v3 接口兼容问题:type=url 已废弃改为 type=path,在线人数字段 x 改为 visitors。密码重置也顺便做了。

fix/search 接入 kbar 全文搜索 · Ctrl+K 修复
2026-04-11d919495

命令面板里的 /search 一直只是跳转到 /blog,算是占位符。这次把它接入了 kbar,执行后会弹出全文搜索框。

根因是 Footer 不在 SearchProvider 内,导致 useKBar() 拿不到 context,Ctrl+K 也跟着失效——把 Footer 移进 SearchProvider 后一起解决了。

javascript
> /search█
  ┌─────────────────────────────┐
  │ 🔍 搜索文章…                │
  │ ──────────────────────────  │
  │   环形缓冲区                │
  │   计算机网络应用层          │
  └─────────────────────────────┘
featUmami 用户行为埋点
2026-04-10510ee4f

接入 Umami 做轻量行为分析。不收集个人信息,只是想知道有没有人真的用了那些快捷键。

javascript
track("nav_click")        ← 导航点击
track("theme_switch")     ← 主题切换
track("lang_switch")      ← 语言切换
track("comment_submit")   ← 评论发送
track("tag_click")        ← 标签跳转
feat像素风格全局 loading 进度条
2026-04-068525d68

路由跳转时顶部出现一条像素风格进度条,比 spinner 更有终端感。

javascript
█▓▒░░░░░░░░░░░░░░░░░░░░  loading…
██████▓▒░░░░░░░░░░░░░░░  loading…
████████████▓▒░░░░░░░░░  loading…
███████████████████████  done ✓
featGitHub OAuth 评论系统
2026-04-058725a4d

基于 GitHub Discussions 的评论系统,整个设计围绕 git log 的视觉语言展开。

javascript
commit a3f9c12
Author: visitor <via OAuth>
Date:   2026-04-05

    这篇讲环形缓冲区的文章写得很清楚

 1 file changed, 1 insertion(+)

[git push]  ← 就是这个按钮
featCode::Stats 主页面板
2026-04-026e0a0a8

主页接入 Code::Stats,实时显示各语言编码时长。

javascript
$ code-stats --user jimmy

TypeScript  ████████████░░░░  62%   1,204 xp
Go          ██████░░░░░░░░░░  31%     612 xp
CSS         █░░░░░░░░░░░░░░░   7%     134 xp
feat环形缓冲区博客 + 交互可视化
2026-03-25a7de334

移植并重写了 RingBufferViz 和 GoGateBufferViz 两个交互组件。GoGateBufferViz 支持手动 read / write,可以一步步看位运算取模怎么工作。写这个比写文章花时间多了。

javascript
    ┌───┬───┬───┬───┬───┬───┐
    │ 0 │ 1 │ 2 │ 3 │   │   │
    └───┴───┴───┴───┴───┴───┘
          ▲               ▲
        read            write

  capacity = 6  (must be power of 2)
  mask     = 5  (capacity - 1)
  index    = pos & mask  ← no division

2026-03

featCatppuccin 主题系统
2026-03-150671bcd

整个博客的视觉基础。用 CSS 自定义属性替换默认 Tailwind 色板,三套主题不跟随系统。

javascript
  Latte     Mocha     An Old Hope
  ──────    ──────    ───────────
  ● #4c4f   ● #89b4   ● #e5cd52   blue
  ● #1e66   ● #cba6   ● #c678dd   mauve
  ● #40a0   ● #a6e3   ● #98c379   green
  ● #d20f   ● #f38b   ● #e06c75   red
feat全局中英文切换(i18n)
2026-03-146c591b5

没用任何外部 i18n 库,自己写了一个轻量的 LangProvider + useLang() hook,localStorage 持久化。约 35 个 UI 字符串都有完整中英翻译。

typescript
const { t, lang, setLang } = useLang()

t.slashBlog // "博客" | "blog"
t.groupPages // "页面" | "pages"
t.noMatch // "无匹配" | "no match"
featPaneLayout — IDE 分屏布局
2026-03-13a596748

最核心的视觉改动。所有页面改为双栏分屏,文章列表用 Unix 文件权限格式渲染。

javascript
┌─────────────────────┬──────────────┐
│  $ ls -la ~/blog    │  tags/       │
│                     │  ──────────  │
│  -rw-r--r-- jimmy   │  #meta    2  │
│  2026-04-11         │  #go      1  │
│  环形缓冲区…        │  #network 1  │
│                     │              │
│  -rw-r--r-- jimmy   │              │
│  2026-03-20         │              │
│  计算机网络…        │              │
└─────────────────────┴──────────────┘
featSlashCommandPanel
2026-03-12f89cc24

底部状态栏里的命令面板。按 / 激活,输入命令跳转页面或切换主题。

javascript
  pages
  | /home      ~/
  | /blog      blog/
  | /projects  projects/
  | /about     about/

  actions
  | /search    grep
  | /theme     toggle

  ↑↓ nav   ↵ select   esc close
> /█
featTerminalPet 桌面宠物
2026-03-11870c256

右下角随机生成的 ASCII 小宠物,5 种稀有度、8 种帽子、5 项属性。传说级有概率出现闪光变体,孵化时有破壳动画。

javascript
        ★ LEGENDARY ★
          [~~~~~]
           /\_/\
          ( ✧ ✧ )   ← 闪光变体
          (  ♥  )
          (*)_(*)

  DEBUGGING  ████████░░  80
  PATIENCE   ███░░░░░░░  30
  CHAOS      █████████░  90
  WISDOM     ██████░░░░  60
  SNARK      ████████░░  80
feat全键盘导航
2026-03-102384e44

没有鼠标也能完整操作整个站点。

javascript
  g → h   go home          j / k   prev / next post
  g → b   go blog          [ / ]   prev / next page
  g → p   go projects      n / p   older / newer
  g → a   go about         u       back to list
  g → c   go contact       ?       show this help
              /             Ctrl+K  command palette
featAbout 页 nvidia-smi 风格
2026-03-08

关于页面模拟 nvidia-smi 的终端输出格式。

javascript
+-------------------------------------------+
| Jimmy  v26.03    sleeprhino.com            |
+-------------------------------------------+
| Skills                    Utilization      |
| TypeScript ████████████░   92%             |
| Go         ████████░░░░░   65%             |
| React      ██████░░░░░░░   50%             |
+-------------------------------------------+
| Processes                                  |
| PID   Name          Status    MEM          |
| 001   Adam Blog     running   ~420MB       |
| 002   GoGate        shipped   ~80MB        |
+-------------------------------------------+
featDiscord 实时状态(Lanyard WebSocket)
2026-03-05

主页通过 Lanyard WebSocket 显示 Discord 在线状态和当前活动,状态实时更新。

javascript
  ● online                    jimmy#0000
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  🎵 Listening to Spotify
     Nightmare — Set It Off
     00:53 ───────●────── 03:12
ciDocker + GitHub Actions CI/CD
2026-03-01

推送即部署,不用手动操作服务器。

javascript
  git push origin main
       │
       ▼
  GitHub Actions
       │  checkout → yarn build → docker build
       ▼
  SSH → VPS
       │  docker stop → docker run
       ▼
  ✓ deployed  (~3 min)