六月杂记:几个小项目和一些生活上的琐事
最近折腾了不少东西。有自己写的项目,有博客的反复搬家,有字体和排版上的微调,也有对代码托管平台的一些整理。中间还夹杂着高中生活开始后的时间紧张,以及刷闲鱼时看到的各种魔幻现实。零零散散,干脆合在一起写篇杂记。
一、自己写了个静态网站生成器
项目叫 Zest SSG,全称 Zealous Efficient Static Toolkit(热情高效的静态工具包)(新全称:Zest: Easy Static-site Toolkit),本质上是个混用 F# 和 C# 的静态网站生成器。最核心的念头是:模板应该是真正的代码,而不是一堆字符串。写模板的语言和主语言,本就该是同一门。
开发这玩意儿,是因为我对市面上不少静态站点生成器越来越不耐烦。很多工具非得让你写 YAML 配置,模板又是另一套怪兮兮的字符串替换语法。我平时用 F#,心里就嘀咕:构建网站时,为啥不能直接跑 F# 脚本呢?于是 Zest 的页面文件变成了 .zest.fsx——它们是实打实的 F# 脚本,在构建时通过 dotnet fsi 执行。你可以随心所欲用 F# 的列表推导、模式匹配、字符串插值,想算什么算什么。
不过我也明白,不是每次都得兴师动众启动 FSI。所以加了 .zhtml 轻量页面:纯 HTML 加可选的 Nunjucks 语法,没有额外开销。还有 HTML DSL,能声明式地写 render [ h1 []; p [] ]。甚至能在 .zest.fsx 里直接用 md 助手写 Markdown,跟 HTML DSL 混在一起用。
样式这块,我不想引 Sass、Less 那些外部依赖,就自己设计了 ZCSS。它是 CSS 的超集,支持嵌套、F# 风格的 let 绑定、数学表达式、颜色函数和 mixin,最后编译成标准 CSS。比如你可以写 let space4 = 0.25r * 4,算好再塞进样式里。
配置上我相当固执:坚决不用 YAML,只使用 TOML。项目里有个可选的 _init.zest.fsx,在构建前跑,能注入动态数据、读 JSON/TOML、读环境变量。
主要功能罗列一下:
- 模板即代码:
.zest.fsx是真 F# 脚本。 - HTML DSL:声明式组合 HTML。
- 内联 Markdown:在脚本里直接混写。
- 标准
.md文件,带 frontmatter。 - ZCSS:带嵌套、变量、数学、颜色函数。
- TOML 配置,零配置可用。
- 热重载、批量评估(多脚本单进程跑)、增量构建、跨平台。
快速开始就几句:
1
2
3
4
zest init my-site
cd my-site && zest serve --port 8080
zest build
zest preview
举个小例子,.zest.fsx 里可以写:
1
2
3
4
5
6
7
let pageTitle = "Hello from F#"
let items = ["F#"; "Zest"; "SSG"]
render [
h1 [ text pageTitle ]
p [ text "This page is generated by real F# code at build time." ]
ul [ for i in items -> li [ text i ] ]
]
ZCSS 例子:
let primary = #3b82f6
let space1 = 0.25r
let space4 = space1 * 4
let primary-light = primary |> lighten(45%)
.tag
color: $primary
background-color: $primary-light
padding-block: $space4
border-radius: 9999px
编译出来就是普通 CSS。
架构分四块:Zest.App(C# 命令行入口)、Zest.Engine(F# 核心逻辑)、Zest.Dsl(F# 预编译辅助)、Zest.Infra(C# 管配置和文件监听)。这样拆是因为 C# 弄命令行省事,F# 弄计算和 DSL 顺手。
写的时候,有几条设计哲学是我刻意坚持的:
- F# 做模板——模板就是程序本身。
- ZCSS 是布局引擎,不是传统预处理器,它吐出 CSS。
- TOML 做契约,绝对不会使用 YAML。这点我尤其坚定,因为以前被 YAML 缩进坑惨过。
- JavaScript 只管客户端交互,不碰 Node、npm、打包器。
- 这工具是给少数爱 F#、恨 YAML、喜欢简单东西的人做的。
这项目能成形,多亏了我几个能干的 AI 助手,它们帮我做设计、调试和文档:Claude 做架构和设计评审,GLM 做调研和实验,DeepSeek 做调试和性能调优,Hunyuan 做实现和文档支持。真心谢谢它们。代码以 Apache 2.0 许可开源。
后来 Zest 更新到 v0.3.1,算是第一个稳定版本。性能增了许多(除却 FSI 冷启那免不了的二三秒),Zest Page 与 ZCSS 语法也大体可用了。但这月我得停更——要上学去。当前 GitHub 组织里只有我一人,没有其他管理员帮忙管理项目。
二、用 Eleventy 重搭了一个三栏博客
当然,现在又迁移回 Jekyll 了
之前我的个人博客用的是 Jekyll + Chirpy 主题,走了本地构建再推送的路,省去了平台构建不一致的麻烦。但那套方案有个绕不过去的限制:Chirpy 主题打包在 Ruby gem 里,能改的只有配置文件和有限的几个 include。如果你想动布局、改色调、换字体——这些在 Chirpy 的体系里都不是“改一行配置”能解决的事。Jekyll 本身又绑定在 Ruby 生态里,插件写起来说实话也不算顺手。
搬到 Eleventy 的理由很简单:它不绑定任何模板语言,不绑定任何 CSS 方法论,连输出格式都不绑定。你想要什么自己搭。副作用是,一切都要自己搭。但正是这种“自己搭”的模式,让 11ty 成了最接近裸写 HTML 的静态站点生成器。你在模板里写什么标签,它就输出什么——不会在你不知情的时候往页面里塞多余的 div、inline script 或 CSS class。这对于一个想精确控制每一行输出的开发者来说,是无可替代的体验。
我把整个项目划分成三个层次。最底层是数据层,src/_data/ 目录下放着一堆 JSON 和 JS 文件。site.json 定义站点名称、时区、每页文章数等全局参数;author.json 存个人信息和社交链接;comments.json 保存 Giscus 和 Twikoo 的配置;taxonomy.js 做中文字段到 URL-safe slug 的映射。还有两个计算数据文件,sidebarCategories.js 和 sidebarTags.js,它们在构建时扫描所有文章,统计分类和标签的频率,输出给右侧栏使用。
中间是逻辑层,一个 .eleventy.js 文件处理所有构建逻辑。包括插件的注册(RSS 生成、代码高亮)、过滤器(日期格式化、阅读时间估算、HTML 剥离、分页导航的 prev/next 计算)、集合的定义(文章按日期排序、分类聚合、标签聚合),以及最重要的搜索索引生成。
搜索索引是一个特殊的集合——searchIndex。它不在模板中渲染成页面,而是在构建时遍历所有文章,读取每个 Markdown 文件,剥离掉 YAML frontmatter,再清除 HTML 标签和 Markdown 标记,截取前 1500 个字符,最后输出成一个 search.json 供客户端使用。这样做的好处是搜索索引在构建时就确定了,用户打开搜索时只需要下载一个预先生成的 JSON 文件,不需要在服务端跑任何查询。
最上层是表现层。布局模板在 src/_layouts/ 下,页面路由在 src/routes/ 下,组件在 src/_includes/ 下。CSS 全部分散在 src/assets/css/ 下的五个文件里:variables.css 存放所有设计变量(颜色、字体、间距、阴影、圆角)、base.css 做 CSS reset 和排版基调、layout.css 定义三栏网格和页面结构、components.css 覆盖所有组件样式(卡片、徽章、分页、侧边栏、搜索弹窗、文章导航、TOC 等)、theme.css 做表面装饰(噪点纹理、悬浮效果、入场动画、回到顶部按钮)。responsive.css 专门处理响应式断点。
没有用任何 CSS 框架。Bootstrap、Tailwind、Bulma——都没有。每一个像素都是手写的 CSS 自定义属性。
左侧栏是固定的 240 像素,包含作者卡片、导航菜单、一个每秒更新的数字时钟,还有一个 JavaScript 生成的当月日历。右侧栏是固定的 260 像素,包含自动生成的目录、站点统计、分类列表和标签云。中间的主内容区自适应填满剩余空间。这个布局在桌面端表现不错,但在平板上我切成了两栏:隐藏右侧栏,左侧栏保持固定。手机上则完全放弃侧栏,左侧栏变成一个从左侧滑出的抽屉式菜单,由汉堡按钮控制开关。响应的断点选在 1200px 和 768px——前者是常见笔记本屏幕的宽度下限,后者是 iPad 竖屏和手机的分界线。
颜色的设计上,浅色模式以柔钢蓝为主色调(#5a8fb4),配以暖灰色背景(#e0e8f0)和白色卡片(#ffffff);暗色模式则切换到暖琥珀色(#e8915a),背景用深灰(#18181b),卡片用略浅的深灰(#222225)。四个辅助色分布在不同的 UI 元素上——分类标签用墨绿系,标签云用暖棕系,侧栏装饰用薰衣草系,代码块用土橘系。用户切换一次主题后,选择会被存进 localStorage,下次打开页面直接复用,不依赖系统偏好。
细节上,所有圆角都设成了 0。这是有意的选择——直角在中文排版里比圆角更接近传统印刷的质感,尤其是配合衬线字体做标题时,直角边框和规整的网格更能呼应纸媒的气质。
搜索功能用了 Fuse.js 做客户端模糊匹配。构建时先生成一个 search.json,结构是一个数组,每篇文章包含标题、URL、日期、摘要、标签、分类,以及截取过的正文前 1500 个字符。用户在搜索弹窗里输入关键词后,Fuse.js 在浏览器端做模糊匹配,权重分配是标题 50%、摘要 25%、正文 15%、标签和分类各 5%。阈值为 0.35,允许单字符匹配——这对中文搜索很重要,因为中文不像英文那样有天然的空格分词。
JavaScript 文件全部手写,没有用 jQuery 或其他框架。主要功能包括:左侧栏移动端抽屉的开闭、返回顶部按钮的显隐(滚动超过 300px 时出现)、阅读进度条(根据 scrollY 与可滚动总高度的比值更新宽度)、标题锚点链接(为文章内容中每个标题生成一个可点击的链式图标,点击后复制完整 URL 到剪贴板)、目录生成(从 h2/h3 提取标题文本构建 TOC 列表,滚动时自动高亮当前章节)、主题切换、数字时钟(每秒更新)、当月日历(JavaScript 渲染,支持前后翻月)、以及搜索弹窗的全部交互逻辑。
Service Worker 在生产环境下注册,用来预缓存站点资源,实现离线访问能力。manifest.json 中定义了 PWA 的基本配置,包括启动画面、主题色和应用名称。
代码推送到 GitHub 后,GitHub Actions 自动执行部署流程。先把 _site 目录上传为 GitHub Pages 的 artifact,然后调用官方的 deploy-pages action 部署到 GitHub Pages。同时我配置了两个额外的推送目标:一个是推送到 GitLab 做镜像仓库,另一个是克隆 Codeberg Pages 仓库,把 _site 内容复制进去,写入自定义域名文件,再推送回 Codeberg。三个平台共用同一份构建产物,确保输出完全一致。Build.ps1 是 Windows 下的构建脚本,逻辑很简单:删除旧的 _site 目录,然后执行 npx @11ty/eleventy。
所有的文章使用同一个 frontmatter 结构。_posts.json 为 _posts/ 目录下的所有 Markdown 文件设置默认值:布局为 post.njk,永久链接格式为 /posts//。每篇文章的 frontmatter 至少包含标题、日期、分类和标签。摘要是可选的,如果不填,首页卡片上会显示正文的前几行。
评论系统同时支持 Giscus 和 Twikoo。comments.json 中配置了两个 provider 的参数,post 布局底部的 comments.njk 组件根据 provider 字段选择渲染 Giscus 的 client.js 脚本还是 Twikoo 的初始化脚本。两个评论系统可以同时启用,读者自由选择。
路由方面,除了文章详情页,系统还生成了首页分页列表、分类索引页、分类详情页、标签索引页、标签详情页、归档页、关于页、友链页、留言页和分享页。这些页面共用 base.njk 布局,各自独立渲染内容区。
从 Jekyll 到 Eleventy,最大的感受不是某个具体功能的好坏,而是控制权的转移。在 Chirpy 主题下,你只能做主题允许你做的事;在 Eleventy 上,你做的每一个决定——CSS 变量命名、布局如何分层、搜索索引的权重分配——都是你自己的决定。当然代价是每件事都要自己动手。如果你喜欢开箱即用,Chirpy 仍然是更好的选择。但如果你想完全掌控博客的每一层,Eleventy 值得花时间。
三、字体和排版上的微调
最近调整博客字体,把正文从更纱黑体换成了小米兰亭。(9月更新:现在换成了思源黑体,兼容性更好一些。)
更纱黑体我用了挺久,它融合了思源黑体和 Iosevka,现代感强、字符齐全。但不知为何,读起来的体验总不如系统默认字体舒服。直到换了小米兰亭,对比才明显:它的字母更粗、更圆润,整体观感柔和,长时间阅读不容易累。小米兰亭设计时就考虑了阅读感受,笔画清晰、灰度均匀,用在博客正文里,字与字之间的呼吸感刚好。
不过,字体效果很大程度取决于系统渲染。Windows 的字体渲染一直是个老问题——ClearType 再怎么调,比起 macOS 原生渲染,总像隔了层纱,换什么字体都难有质的改善。iOS 这边则不论什么字体,线条清晰、边缘平滑,赏心悦目。Linux 上,至少 KDE Plasma 开箱即用的渲染不错,字形和间距都舒适;其他桌面环境我没深入用,不作评价。
字体选择也不能光看个人偏好。我博客文章标题原本用繁体,觉得有古风质感,正文用简体便于阅读,但朋友常吐槽看不懂标题。后来换字体,一直找不到华英明朝体的感觉,折腾半天才发现:ZSFT 默认提供的华英明朝体本有简体版本,它却默认调用了 T 字符集的繁体版,而非 Classic 简体。修改后标题回归简体,质感稍差一点,可读性却大大增强。
说到底,字体没有绝对好坏,只有合不合适。如果博客以正文为主,想在 Windows 和 macOS 间找平衡,不妨试试小米兰亭。至少目前,它是最让我舒服的阅读字体。
至于人气很高的霞鹜文楷,个人认为它更像手写楷体,而非标准印刷楷体,在计算机字体分类里接近艺术字。很多人喜欢它比印刷体多出的温度与活力。但艺术字用于正文并不理想,风格也和我的博客调性不符。
另外,Linux 默认字体大多从文泉驿系列转向了思源系列。思源黑体中庸平稳,比略显稚气的文泉驿微米黑成熟。以前缺好开源字体,发行版才偏爱文泉驿;如今多数发行版和桌面环境都已内置思源宋体、黑体。
排版方面,我还花时间处理过一个看似微小、却影响阅读气质的细节——中文正文的首行缩进。
起初做法简单粗暴:给所有 <p> 标签加 text-indent: 4em;。视觉上,段落整齐右移四格,有了传统印刷品的秩序感。但问题很快出现:滚动到列表或引用块时,因为结构常是 <li><p>,里面的段落也被缩进,显得错位且不协调。这让我明白,不能一刀切,得分清边界。
Halo 主题(及多数现代 CMS)为了语义化,常把列表项文本包在额外 <p> 中。直接选 p 会误伤。解决方法是划定范围。我放弃全局 p,改用排除选择器锁定正文段落:
1
2
3
4
5
p:not(li p):not(blockquote p) {
text-indent: 2em;
margin-top: 0.8em;
margin-bottom: 0.8em;
}
这样只缩进直接属于内容的段落,列表和引用内的不被影响,排版恢复逻辑。
过程中还定了几点准则:一是用 em 而非 px,响应式设计中固定像素不能随字号变化,em 相对单位能自动伸缩;二是移动端微调,小屏上过宽缩进会挤压阅读空间,因此加媒体查询,屏幕小于 480px 时缩进从 2em 减为 1em。
最终,只用了一段不依赖 JavaScript 的 CSS,未改动 HTML 结构,完成了视觉秩序校正。这种“只动样式,不动结构”的思路,不仅适用于 Halo,对 Typecho、WordPress 及静态博客生成器也通用。不过后来因为显示 Bug 较多,本站已放弃正文段落首行缩进。
四、GitHub 之外的代码托管平台
老实说,到了 2025、2026 年,GitHub 已经不再是“偶尔抽风”,而是经常出问题:免费 Actions 分钟数被大量机器人挖矿账号占用,正常用户排队很久;安全漏洞修复缓慢,供应链攻击时有发生;国内访问不稳定,CI/CD 一跑就卡,部署像抽奖。最让人不满的是,微软似乎不太在意免费用户,企业版卖得火热,免费用户却被忽视。很多人忍无可忍,开始找备选。国内、海外、自建方案都看一看。
国内平台普遍要求强制实名和手机号绑定,这是绕不开的门槛。Gitee(码云)是目前国内最实用的选择。访问速度快、稳定性高,功能基本齐全:Pages、Wiki、Issues、PR、Release、Actions(虽弱但能用)。可以外链项目卡片,免费私有仓库多,中文社区完善。但 Actions 算力有限,免费额度用尽便无法使用,敏感内容可能被要求整改。如果人在国内、需要日常开发和速度,Gitee 是唯一靠谱的国产主力。
GitLink 由 CCF 和中科院背书,完全开源,支持 Pages、Wiki、Issue 等。但名字易与 GitLab 混淆,社区活跃度低,Issue 响应慢,国内访问一般。学术圈可考虑,日常开发还是 Gitee 更稳。
Coding(腾讯云)有大厂背书,企业级服务稳定,支持 CI/CD、项目管理、代码托管一体。但免费额度少,付费门槛高,界面臃肿,操作繁琐,数据隐私存疑。企业用户可考虑,个人开发者不建议。
海外平台方面,Codeberg 由德国非营利组织运营,完全开源,数据受 GDPR 保护。Pages 功能强,支持 Hugo/Jekyll 等静态生成器。社区友好,人工客服响应快。国内访问需代理,社区规模小。追求开源精神和隐私,这是首选。GitLab 功能齐全,CI/CD、项目管理、托管一体,自托管版免费。但商业化重,免费版受限,国内访问慢。企业用户可考虑。SourceHut 极简设计,无广告无追踪,完全开源。界面简陋,新手不友好,国内需代理。极简主义者可选,不适合大众。
自建方案里,Gitea 轻量,资源占用低,完全开源,支持 Pages、Wiki、Issue 等。需自维护服务器和备份。有服务器资源的开发者首选。OneDev 实现 DevOps 一体,托管加 CI/CD 加项目管理,轻量开源。同样需自维护。
GitHub 不再是唯一。国内用户可选 Gitee 主力,海外选 Codeberg 追开源,有服务器可自建 Gitea 或 OneDev。重要的是找适合自己的,而非被单一平台绑定。
五、闲鱼二三事
闲鱼是个神奇的地方。这里几乎啥都有,黑市敢卖的它敢卖,黑市不敢卖的它也敢卖。抛开那些乌烟瘴气的,单从程序员视角看,在闲鱼搜“GitHub”,出来的商品就让人瞳孔地震。最夸张的莫过于刷星、自动发货的账号交易、PR 造假、源码代下载……但这还不是最离谱的。最离谱的是各路商家晒着疑似脚本刷出来的贡献墙,明码标价兜售“大学生作业代做”。什么编程语言都接,装得跟真·技术大牛似的,买的人居然还不少。
我知道不少大学生进了大学就撒野放纵,但说句实话,玩归玩,闹归闹,课别天天翘,哪怕进去听一丁点儿呢?这纯属交冤枉钱。而且这些商家大概率也是拿 AI 做的项目,你花同样的钱买 Token 呢?至少能学会怎么用 AI,怎么 Vibe Coding,总比彻底躺平、不学无术强吧?抖音、B站上铺天盖地都是 AI 焦虑的视频,可另一头,居然还有大学生心甘情愿把钱送给闲鱼上的无良商家。我严重怀疑咱们根本不在一个时间线里。既然学了计算机,网上一点职业相关的动态都不刷吗?2023 年 AI 还没成气候也就罢了,今年都 2026 年了!
更让我匪夷所思的是,Java 和 C++ 代做也就忍了,连 Python 项目都有人找代做!我想说的不是 Python 有多简单,这早就不是难度的问题了。现在随便一个网页端 AI Agent(比如智谱清言 GLM、MiniMax)都能开发 Python 软件,Django、Flask 这些框架都能开发,还全是免费的。哪怕稍微了解一下当下的 AI 发展现状呢?根本没必要花这冤枉钱,难道网页都不会打开吗?这种思维逻辑本质上就是得过且过:能花钱解决就绝不费脑,绝不多思考一秒。这是一种极其弱智的生存策略。
这类网友我见过一些,也有一些是认识的朋友:比如某程序开发专业的大学生,在某个开源项目的视频底下问 Git 是什么、GitHub 为啥打不开;还有我在某个 Q 群里认识的网安专业老哥,大学混了三年,光顾着玩,电脑都没碰过一下。古有指鹿为马,今有指 Linux 为华为系统,而 Windows……被誉为安卓电脑。
如果说上面那是“蠢”,那接下来的操作就是纯粹“坏”了——利用开源项目牟利。闲鱼上有些给 GitHub 刷贡献墙的商家,但稍微搜一下就知道,这玩意儿就是 GitHub 上的一个开源工具 GreenWall(绿墙)。想要多少贡献随便填,全刷绿都行。可即便如此,依然有人花高价买这玩意儿优化简历。项目地址在这里。
当然,我也凑了个热闹,花了十几块钱,分别买了个刷星服务和一个新账号尝鲜。刷星服务倒是挺“专业”:那些刷星的假号有模有样,有 Issue、有 PR、有仓库还有 Fork,还是分批刷的,估计是为了躲风控。这点确实有一手,不过还是不提倡刷星,毕竟懂的都懂。听说 OpenClaw 就是刷星刷出来的项目,微软那边基本是睁一只眼闭一只眼。至于那个新账号……说实话,毫无卵用。真不如手动注册。大家想看可以去这瞧瞧:https://github.com/exyone-dev。我已经换上了自己的 ID、密码,绑定了邮箱和 2FA。总结就是:除非这账号自带 GitHub Pro,否则真没必要买,纯属智商税。哪怕你是想要整一个老号,也用不到这玩意,上面那个绿墙工具就能帮你实现了,在十几年前的年份刷贡献就可以让那一年出现在贡献墙上,也因此可以让账号看起来资历更老。
更新:买的这个账号似乎已经被 GitHub 云控了,现在无论是提交 PR 还是创建 Issue,别人都是看不到的。
六、再谈张雪峰和计算机专业
张雪峰是一个极具争议性的人物,但不得不指出,计算机专业的混子数量之多,和张雪峰绝对脱不了干系。张雪峰在两、三年前的时候力荐计算机专业,导致大量大一新生涌入计算机专业,质量参差不齐是一方面,另一方面,计算机专业是一个对学习能力要求极高的专业。那时候,张雪峰的话被很多家长奉为圭臬——尤其是那些自身毫无主见、却又控制欲极强的家长。他们只记住了“计算机好就业”,但对专业内容、行业门槛、孩子特质一概不知。
更令人唏嘘的是,这批学生的家庭背景大多透着一种无力感:很多孩子从小到大几乎没正经碰过电脑,结果刚进大一,家长反倒大手一挥,直接配齐了“华为全家桶”。让一个对计算机毫无基础、心智尚未成熟的孩子,突然闯进一个极度依赖自学能力和信息素养的领域,本身就埋下了隐患。这些大一新生接触到外面的世界之后变得浮躁了,完全沉不下心去学习了。
在两、三年前,网络上还有人会说:“计算机和起点无关,穷人家的孩子只要肯学,照样能出头。”当然,这句话确实说得很对,我也支持这种观点,但现实情况是绝大多数人根本没有那么好的自控力;小学和中学,孩子没有接触过外面花花绿绿的世界,还能保持朴素的心态,可一旦踏入大学,诱惑扑面而来,还能守住本心、不随波逐流的人少之又少。这就好比把一只从小关在笼里的鸟突然放飞,却指望它依然安分地在铁栏里歌唱——未免太过理想化。计算机专业对学习能力的要求极高,因为技术栈只会不断更新迭代,没有人能靠着 jQuery 和 BootStrap 干一辈子不失业。如今,再没人敢轻易劝人学计算机了。为什么?因为一个几年前人挤人的专业,稍有常识的人都看得出来:迟早该饱和了。

