MoreRSS

site iconThe Wandering Allison修改

试图找回自主表达权的普通人。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

The Wandering Allison的 RSS 预览

Digital Declutter 之图床清理:GitHub 到 Backblaze

2025-09-13 08:00:00

说好的不折腾博客呢!(心虚的我)

之前 写过 我把博客图床从 GitHub 换到了 Backblaze,但历史遗留问题还在这儿:

  • 部分博客图片还在 GitHub
  • GitHub 中大部分图片不是 WebP,所占空间不小
  • GitHub 中部分图片为错误或重复上传,未被使用

目前用作图床的这个 GitHub 仓库有 540 MB,而 GitHub 官方对单个仓库的建议大小是不超过 1 GB。尤其是换到 Backblaze 并且全部采用了 WebP 格式之后,真是横看竖看旧仓库不顺眼,所以,忍不住来整顿了。

前期准备

  • git clone GitHub 图床仓库到本地
  • 本地电脑存有全部博文文档 (之前写过我日常所有文档都在 obsidian 里,博文部分是用 GitHub action 同步到博客 content/posts 文件夹,所以不成问题)

操作流程

处理 GitHub 图床图片

Python 脚本:

  • 遍历博客文件夹中的 markdown 文件,筛选出 markdown 图片链接(![]())中含有 GitHub 图床地址的所有文件名
  • 将文件名和图床仓库图片文件一一比对,输出缺失和未使用图片名称
  • 将在博文中被使用的非 WebP 格式图片转换成 WebP,移除原始图片
  • 未使用图片移至新文件夹
import re
import shutil
from pathlib import Path
from PIL import Image
import urllib.parse

# ---- Config ----
MARKDOWN_DIR = Path(r"md_files_folder") # folder containing .md files
IMAGE_DIR = Path(r"images_folder") # folder containing images
REMOVED_DIR = IMAGE_DIR / "removed" # where to move unused images

# Regex: capture filenames after "master/"
DOMAIN_PATTERN = r"master/([^/\s]+\.(?:png|jpe?g|webp))"

# ---- Step 1: Extract image filenames from .md ----
image_refs = set()
for md_file in MARKDOWN_DIR.glob("*.md"):
 with md_file.open(encoding="utf-8") as f:
 text = f.read()
 matches = re.findall(DOMAIN_PATTERN, text, flags=re.IGNORECASE)
 # URL-decode the matches so %20 etc. map to real filenames
 decoded = [urllib.parse.unquote(m) for m in matches]
 image_refs.update(decoded)

print(f"Found {len(image_refs)} referenced images.")

# ---- Step 2: Identify unused and missing images ----
used_files = set(image_refs) # decoded names from Markdown
local_files = {f.name for f in IMAGE_DIR.glob("*")} # actual local filenames

unused = local_files - used_files
missing = used_files - local_files # referenced but not found locally

print(f"Unused files ({len(unused)}): {sorted(unused)}")
print(f"Missing files ({len(missing)}): {sorted(missing)}")

# ---- Step 3: Move unused images ----
REMOVED_DIR.mkdir(exist_ok=True)
for img in IMAGE_DIR.glob("*.*"):
 if img.name not in used_files:
 shutil.move(str(img), REMOVED_DIR / img.name)
 print(f"Moved unused: {img.name}")

# ---- Step 4: Convert remaining to WebP ----
for img in IMAGE_DIR.glob("*.*"):
 if img.suffix.lower() != ".webp":
 try:
 with Image.open(img) as im:
 webp_path = img.with_suffix(".webp")
 im.save(webp_path, "WEBP")
 img.unlink() # delete old file
 print(f"Converted: {img.name} -> {webp_path.name}")
 except Exception as e:
 print(f"Failed to convert {img.name}: {e}")

中途踩到了一些坑但感觉这会非常因人而异,教训之一是在各步骤输出结果并及时比对数据,还有慎用删除,提前备份。

批量上传图片到 Backblaze

平时插单张图片我用 Obsidian + PicList ,这里一下子有三四百张需要批量上传,用 Backblaze B2 Command-Line Tool (B2 CLI) 会方便些。

Install the B2 CLI:

pip install b2

Authorize Your Account:

b2 authorize-account

Upload the Folder:

b2 sync images_folder/ b2://my-photo-backups/

替换博文图片链接

用 vs code 的 regex replace 把旧地址全部换成 Backblaze。也就是把原来的 https://raw.githubusercontent.com/{username}/{repo}/{branch}/{filename}.jpg|jpeg|png|webp 换成 Backblaze 经 Cloudflare 中转后的地址,{cloudflare_worker_address}/{filename}.webp 。 Cloudflare worker 部分在上次的 更换图床博文 里也写过了。

处理旧站图片

到上一步其实就可以结束,把 GitHub 图床仓库删除就行了。但我在旧地址 github.io 下保留了部分工具性博文,那边还是用的 GitHub 图片链接,而要是一并也更换成 Backblaze,墙内访问会看不到图片。用上面类似流程筛选了一遍,把 github.io 用到的图片以 WebP 存到原图床 repo 的另一个 branch,删除原始 branch。批量更换 github.io 下图片地址。

结果

  • GitHub 图床:540 MB(400+ 图片) –> 5.4 MB (61 张图片)
  • Backblaze bucket:博客所有图片,20+ MB

另外看了下现在 GitHub 上各仓库的大小,这个博客的源码仓库,9.6 MB(因为有两个 branch 分别托管到 github.iovercel.app)。我的 obsidian 文档同步仓库,2.4 MB。果然纯文本最高!上千个文件才这么点地儿。

2025八月读书记录(一)

2025-09-09 08:00:00

极其短小的一期。

ISLAND STORM

ISLAND STORM|600

ISLAND STORM|600

ISLAND STORM|600

小岛上暴风雨来临的一天。

果然是 Sydney Smith 啊!云、海、雨,纹理和色彩表现一如既往。画面和文字的节奏张力完美结合,隔着屏幕都好像也感觉到暴风雨来临前后那急促、紧迫的压力。

如何找到想做的事

狗屁不通,硬着头皮读了1/3的我简直是个智障。再看日式鸡汤我就是猪!这种写作水平连发公众号或者博客我都嫌注水过多。

Is a River Alive?

麦克法伦这本实在是硬凹概念过头了。前两章厄尔多瓜的云雾森林和印度受伤甚至消失的河流也还可以说不错,但第三章加拿大从开头就直接崩塌,用神棍的预知做钩子,结果是所有论证都撑不住,连续上百页没有事件没有人物,只有几个人在河上漂着,哪怕语言再精妙再准确还是空洞。

我是很想展开聊的但估计没有个几千字说不清,上个月倒是反复和 ChatGPT 吐槽了上百句不止。不过 Washington Post 的这则评论也是够狠的了: Unfortunately, Macfarlane is also prone to overwriting and the kind of breathless observations that strike people on drugs as profound. “Everything is connected to everything else,” he gushes at one point. “Hurt people often hurt people,” he remarks later, in the manner of an elementary schoolteacher. There is a lot of awed and emotional crying. 有付费墙,放个可以直接观看的链接吧:Rivers deserve to be protected. But are they ‘alive’?

You’ll Find Me

You’ll Find Me|600

忘了搜什么结果 Libby 只蹦出来这个于是顺手一读。主题概况起来应该是“move on”和“与我常在”。文风对我来说太治愈美文了。画风也不是我偏爱的,就只有上面这个场景还行。但看 goodreads 上 4.3 的评分就知道很多人吃这套。

The Pilot and the Little Prince

小王子作者圣埃克絮佩里的传记绘本。文字不算出众,但画面美得惊人。尤其各种抽象符号图案的精美程度,都让我忍不住嘀咕这画儿童绘本也有点浪费吧(……)。立刻去看画家名字,好的,Peter Sís。

The Pilot and the Little Prince|600

Snipaste_2025-08-06_00-16-18.png|600

The Pilot and the Little Prince|600

Madlenka

Madlenka|600

Madlenka|600

身居纽约,神游世界。

必须得说其中颇有一些刻板印象,但视觉效果惊人,Peter Sís 这极其精美繁复的画风真是让人移不开眼。

In Defense of Food

是这样子的,前几个月有本我没看下去愤而打两星的书,中途已经忍不住疯狂和 ChatGPT diss 作者了,结果 ChatGPT 说啊哈他就像一个缺少事实依据且过度迎合大众贩卖故事的 Michael Pollan,我笑得不行说这是不是辱 Michael Pollan 了。然后想起来之前读了一点他的《杂食者的两难》觉得还不错,正好现在有 Libby 账号可以借英文版听听,但没想到 The Omnivore’s Dilemma 这么抢手暂时没有可借副本,就随便挑了他的这本。结果是……不太行。论证是相当站不住脚。豆瓣这则评论例子举了很多,我就不多费唇舌了。(但是我应该还是会去听 The Omnivore’s Dilemma 的,……吧?)

Can You Keep a Secret?

故事和绘画只能说说得过去,但 Stephen Fry 这么一读立刻把有趣程度拔高了好几档。

Starry Messenger

Starry Messenger|600

Starry Messenger|600

Peter Sís again.

伽利略传记绘本。审判这两张相当惊艳。就是 Peter Sís 太爱用花体字了,我看不清!

Best Foot Forward

Best Foot Forward|600

想看这个作者另外一本关于动物界建筑师的书,Libby 上没有,同作者名下有这本就借来读了,定位应该是童书,简单的动物摄影集,有各种稀奇古怪动物,超高清大图,我觉得不是所有人都接受得了。挑了张最无害的图,猜猜这是谁的爪子?

2025三月读书记录(二)

2025-09-07 18:15:37

以月度为单位写总结的问题是一本卡住整月搁浅。第 N 次思考是不是应该转换一下模式。

抓住十二只喜鹊的尾巴

东欧观鸟人笔记。3.5 星。

湖畔末日冰冷得令人打冷战。其他篇目在观鸟文章中算不得突出,倒是全世界观鸟人的心情都是如此相通,以及大家未免都摄入了太多英美鸟书鸟片。鹰雄一章讲 J.A.Baker(游隼 The Peregrine 的作者) 过于表面远不及 Robert Macfarlane 在《荒野之境》中的讲述。

此外这个译本,它是从波兰语直译过来的,很流畅不错,但是,有点过于流畅甚至“假滑”,可我又不懂波兰语只能说这是我微妙的直觉。整本书聊的内容,其实都是很落地很实际的,参加野鸟观测,给迁徙鸟类戴上环志,对城市里的鸟类保护和绿地丧失的关注和愤怒,都并不是那种过于诗意、抒情的写作。

而且前言就写了:

说来也怪,在学校写作文时,我会非常谨慎地斟酌用词。因为我很快就意识到,语文老师教的未必正确——有时重复某个含义准确的词比勉强去找一个花哨的近义词要强得多。这就是为什么我不会用“有翅膀的探险家”这样故弄玄虚的说法来代替“鸟”这个词。

那中译本是怎么处理的呢?就抽两个章节名来看看好了:

  • Sosnówka pachnąca żywicą──A resin-scented pine grove──雀鸣亮,松脂香
  • Człowiek, który został sokołem──The man who became a falcon──鹰雄

有必要吗?尤其“鹰雄”,我不认为这里有任何的需要处理成谐音梗。何况 Baker 这本书的精神和人类的“英雄”没有一丝一毫的联系。强调男性性别更是完全多此一举。再则,Baker 迷恋的是游隼,falcon 隼,气质和“鹰”也是不同的,这种微妙的氛围和风格传达真的不需要玩弄花招,反倒弄巧成拙。

一些摘抄和关联书单:Notes|抓住十二只喜鹊的尾巴

我们唱歌的鸟、我们花园里的鸟

之前读过同系列的《我们迷人的鸟》(见 2023九月记录 ),这两本依然延续了诙谐幽默的风格,分别讲的是鸣禽和花园常见鸟类。部分鸟类名称翻译有问题,懒得一一复制把笔记截个图(未包含全部错误),阅读中文版时记得不要全盘参照它的译名。

image.png|600

一神论的影子

中国哲学家赵汀阳和法国人类学家阿兰·乐比雄的(不太成功)跨文化交流。赵一心宣讲,阿节节败退。看得我是乐不可支。

两方都不能够说服我,但当然是乐比雄更没论据一点,他甚至只能循环论证用天主教里的“圣人”、“神迹”来捍卫观点,这还有什么说服力?赵汀阳当然就毫不留情步步紧逼,诸多对一神论和西方“现代观”的灵魂质问过瘾至极,让一神教黑子我本人哈哈大笑。只是赵汀阳所推崇的所谓东方思想“天下体系”,又实在是太过儒家了,我也没办法全盘赞同。

不过呢,这种交流本来就难以(或者说,不可能)得出一个盖棺论定的结果。事实上,能有这么一位对宗教信仰甚笃的朋友接受你的质疑,愿意开诚布公探讨,并且双方都有较为资深的人文水准,这个过程就已经弥足珍贵。

看的过程疯狂摘抄,回头单独发吧,塞在这里有点太满了。

Five Flying Penguins

故事太幼稚,画面也不写实,哪有五种长相不同的企鹅生活在一起的道理。可能唯一的作用是让小孩学会数数。

读库1304

之前说过,我很喜欢读库 “建筑史诗”系列,但读库自营图书定价偏高且折扣吝啬,在多抓鱼买二手通常是定价 5 折左右,还可以接受,可惜大家都抱着同样心思导致相当难抢,最后我灵机一动,想到建筑史诗的前几本在读库 mook 上连载过,于是买了这么古早(2013 年)的一期回来。(补充,现在多抓鱼上建筑史诗的折扣甚至只有 7-8 折,但也几乎全系列断货,太夸张了吧!)

所以,重点就是《汉家陵阙》。

汉代木构建筑地上部分实则早已灰飞烟灭,只能从陵墓、封土、砖画中遥想汉风。一些我非常意外的知识点,唐时人们就已经只能感叹“西风残照,汉家陵阙”。另外今天我们都还在使用的许多表述,实则脱胎于汉时的日常。比如“买东西”,最早是出自汉代的东西市城市规划,故用来指代采购行为。还有用“五陵少年”指代世家子弟,是因为汉时陵墓群外常伴有卫星城,居住者多为高门望族,为帝王守墓(或者说,护卫?毕竟不是后世那种犯错被贬守皇陵)。

而这里面最最精彩的部分是试图还原霍去病之墓,尤其封土、石刻之设计初衷。不夸张地说当时我甚至看得屏住呼吸,鸡皮疙瘩起一身。

而这也正是毫无建筑背景知识的我为什么会如此着迷这个系列的原因(主要是中国部分):我并不关心技术细节,我感兴趣的是建筑中体现的古人审美观和世界观。尤其是,其中的很大一部分在不知不觉中也塑造了现在的我。

更细的点会写到后续建筑史诗的专题文里(实在是这里再展开就没完没了了!)。

哦另外提一嘴,这是杂志,所以收录了好几篇文,本着买都买了那就随便一看吧。好嘛,第一篇《下乡养儿》就把我气得半死,零分都不值,只能倒扣。

《下乡养儿(上)》讲的是一对夫妇为了帮八岁的女儿天天克服上学恐惧,在朋友的帮助下举家搬到农村,希望更广阔的天地能让天天渐渐勇敢,回到学校。一个来月的乡下生活确实让天天有了不小的变化。

我一直尽力避免对作者以及非虚构作品的人物进行直接人身攻击,但这篇实在是让人脱口而出:“你们一家是不是都有病?!” 这小孩儿没法上学,在家待着整夜开灯不睡,必须大人陪玩,原因是“我怕”,到底是在怕什么?家长也不想着外力介入,就只会全家一起熬夜,甚至辞职在家陪着通宵,之后又搬家到城郊。实在是不懂这家人脑子里到底在想什么?写得又极其差劲,说流水账都是抬举这文笔。

但气性过去了我又想,我应该真的没法有小孩,控制狂+龟毛,不是小孩被逼疯就是我自己被逼疯。

念念远山

不是山的自然史而是文化史。对于山峰,从畏惧、躲避,如何变成了攀登、“征服”。不过数百年时间,就对群体完成了这样的观念改造。而这种登顶的执念,和极地探险的风靡一时如出一辙。

珠峰一章说实话让我觉得太过傲慢,甚至恶心。不是说作者写得不好,他显然也明了那样的热潮中充满了西方社会的一厢情愿和自以为是。只是在这种叙述和追溯中我隐隐想明白为什么始终我对所谓的狂热“登山爱好者”以及“攀岩爱好者”有不知从何而来的抵触。这其中有多少昔日帝国主义和殖民主义的遗存,谁能说得清呢。

而出道作品就写得这么完整成熟,厉害厉害。这本是我读过的几本麦克法伦中文译本中质量最好的,译者有些词的选择都让我惊叹,原来中文里还有这么凝练又精准的表达!有古意,又不会落入滥用成语的窠臼,多是精巧的单字或短语(很多在现代汉语里已经罕见),反倒把原文那种炼字且极具学者气质的语言风格还原了出来。但这位译者(在这个笔名之下)居然只有两本译著,好意外。

Fixing Trailing Slash Issues in Waline Comments on Hugo Sites

2025-09-07 08:00:00

哈真是绝啦!新评论区才上线大半天我就开始修 bug。并且追根究底后发现只有我这样同时使用 Vercel 托管静态博客 + 用 Waline 做评论系统的倒霉蛋才会碰到!

问题

  • Hugo 生成的 .RelPermalink 默认带有 / 结尾,例如 /post1/
  • 使用 Vercel 托管的站点,输入 https://example.com/post1(没有 /),页面仍然可以访问,并且浏览器地址栏不会自动补全 / 或重定向。
  • Waline 默认使用 window.location.pathname 读取的是当前页面 raw strings 作为评论 thread 唯一标识符。

所以:

  • /post1/post1/ 会被当作两个不同的 thread。
  • 同一篇文章会出现两套评论。

解决方案

方法一:强制重定向

在 Vercel 配置中,强制用户访问带 / 的标准 URL。

在 Hugo 根目录下新增 vercel.json 文件:

{
 "redirects": [
 {
 "source": "/:path*",
 "destination": "/:path*/",
 "permanent": true
 }
 ]
}
  • 这样,当用户访问 /post1 时,会自动重定向到 /post1/
  • 保证 Waline 永远使用同一个标准路径作为评论标识。

方法二:指定 Waline path

在 Waline 前端配置中手动指定 path,用 Hugo 的 .RelPermalink 代替 window.location.pathname

<script>
 Waline.Init ({
 el: '#waline',
 serverURL: 'https://your-vercel-app.vercel.app',
 path: ' {{ .RelPermalink }} '
 });
</script>
  • Hugo 的 .RelPermalink 一定带 /,例如 /post1/
  • 即使用户输入 /post1,评论系统也会固定使用 /post1/ 作为唯一 thread。

相关链接:


问题发散的分割线

一开始我只是意识到同一篇博文下的评论没有同时显示,仔细看了半天链接才发现只是一个 / 的问题。去看 Waline 的 issue 也有人提,作者说这两个路径根本上就不同,所以要改应该是自己改站点设置或者 Waline path 指向,而非要求 Waline 官方将这作为 issue 解决。他说的也确实有道理。

那我的疑问就是,为什么?浏览器和服务器端为什么能把这两个链接当同一个页面处理?而且我之前从来没意识到少打多打一个 / 的问题。再加上用静态站和 Waline/Twikoo 的人这么多(其中还不乏大把小白),之前好像也没怎么见到别人说评论的问题。

正巧我手上还分别有 GitHub Pages,Netlify 部署的静态站,加上这个 Vercel 的站点,试来试去发现原来只有 Vercel 不会自动重定向!有 // 确实都能正常访问。而用 GitHub Pages 或者 Netlify 托管的站点,会自动补全 / 并重定向到标准 URL,所以根本没有缺少分隔符而导致评论被分流又或者统计工具里把 /post1/post1/ 当不同页面来统计的问题。

我就说之前为什么在 Umami 里老是看到同一个页面的不同统计!所以要是治本的话,应该强制重定向和改写 Waline path 一起进行,因为影响的是不同方面。而据此我还发现我这个主题在生成单个页面上的 tag 和 category 链接时也是没带 / 的。于是又吭哧吭哧改代码。

接着就是原来评论的问题。我想把它们重新导入同一个页面,可数据库 LeanCloud 改起来超级麻烦。Waline 本身提供了一个导入导出服务,不过它不能像 Disqus 那样指定路径导入,会清空原有数据完全重写,所以不能选择性导入导出。更过分的是我只是改了下 URL,再导入就连 parent thread 也失效了!这时我又觉得 Disqus 也还挺好。但也不能强求个人项目做得和商业公司一样尽善尽美是不是?而且我看看官方文档,觉得真的写得也挺详尽了,感觉如果是我可能项目和文档做到一半就暴走了……

再然后没忍住又研究了下各大商业网站的跳转逻辑,发现它们几乎都会做重定向。但有些站点,比如网址是 /page.html,再加个结尾 / 就会 404。互联网我都用了 20 年了,过去怎么从来没注意一个微妙的 / 都会有这么多问题,难道我一直是瞎了吗……

更换评论系统到 Waline

2025-09-06 08:00:00

速记一下更换评论系统到 Waline 的过程。

注册数据库

跟着官方 快速指引 注册了 LeanCloud,后续才看到其他人建议说用 MongoDB 读取速度会更快一点。算了,我这站估计也不会有多少评论。

Deploy to Vercel

跟着官方教程走,一键部署到 Vercel。

部署成功后需配置环境变量。

必填项

数据库相关

  • LEAN_MASTER_KEY
  • LEAN_KEY
  • LEAN_ID

其他自定义配置

我用到的部分。

禁止显示评论者信息

  • DISABLE_USERAGENT: true
  • DISABLE_REGION: true

评论头像

  • GRAVATAR_STR: 默认为 https://seccdn.libravatar.org/avatar/{{mail|md5}},我换成了 Gravatar 地址 https://www.gravatar.com/avatar/ {{mail|md5}}

邮件相关

  • SMTP_PASS Gmail 需使用 app password 而非邮箱密码
  • SMTP_USER 邮箱地址
  • SMTP_SERVICEGmail
  • SITE_URL: 站点地址
  • SITE_NAME: 站点名称
  • AUTHOR_EMAIL: 管理员邮箱,添加后管理员发送的评论不会触发邮件提醒。
  • SENDER_NAME: 自定义发送邮件的发件人

建议单独注册邮箱作 STMP 服务,不要和日常邮箱混淆使用。

安全相关

  • IPQPS 同一 IP 发送评论时间间隔
  • AKISMET_KEY 识别垃圾评论

全部完成后访问 Vercel 项目地址,首个注册用户即为管理员。

在站点中引入 Waline

配置 config 文件

config.toml 中的 params 下添加:

[params]
# Waline
 walineServer = "https://your-vercel-project-url.vercel.app/"  #waline vercel 地址 
 walineLang = "en" #设置 waline 语言
 comment = true

新建 comment.html

default/partials/ 下新建 comment.html 文件。

<link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css" />

<div id="waline" style="margin-top:30px;"></div>
<script type="module">
 import { init } from 'https://unpkg.com/@waline/client@v3/dist/waline.js';

 init({
 el: '#waline',
 serverURL: '{{ .Site.Params.walineServer }}',
 path: '{{ .RelPermalink }}',
 locale: {
 placeholder: '邮箱为必填(地址不会被公开)。若需显示头像,在 gravatar.com 使用同一邮箱上传图片即可。'
 },
 lang: '{{ .Site.Params.walineLang }}',
 emoji: [],
 requiredMeta: ['nick', 'mail'],
 search: false,
 WalineImageUploader: false
 });
</script>

Emoji 调整为空。Gif 图片搜索关闭。langserverURL 都是引用的 config.toml 中相应 params 下的值,也可以直接写在这个文件里。requireMeta,用户名和邮箱设置为了必填。

引入评论 partial

single.html 文件最后添加:

{{ $show := .Site.Params.comment }}
{{ if .Params.hideComments }}
 {{ $show = false }}
{{ end }}

{{ if $show }}
 {{ partial "comment.html" . }}
{{ end }}

这个 if 语句是因为我这个站点博文评论 property 是 hideComments,要根据各个站实际情况调整。

移除原有 Disqus 评论代码。

导出与导入评论

在 Disqus 中选择站点导出评论,到 Waline 官方页面 转换评论格式。将转换后的文件导入数据存储后台。

只是我转换完了懒得导入了,就当从头开始吧。

微调站点 CSS

这个就因站而异了,打开页面布局改改 margin padding 还有文本框高度之类的。


流程走完的聊天分割线。

前两天在毛象上和友邻们聊到 Disqus 会插广告的问题,当时我确认过虽然我的 Disqus 是免费版,但不知怎么也没有广告。只是这全仰仗商业公司的决定,就想还是把评论换掉。

中文的静态博客基本不是 Waline 就是 Twikoo,看上去这两个也没太大差别。

我选了 Waline 后纠结的一些问题。

一,默认显示评论者浏览器和地区(可以关掉)。默认记录评论者 IP (后台记录,无法关闭)。

Twikoo 在这方面应该差不多。这样的设计我认为一开始就应该避免,尤其不应该把来访者信息公开设为默认。我不确定有多少人是因为不会设置而选择了公开。至于记录具体 IP,知道这一点之后我不会去陌生的网友评论区留言了。哪怕我的 IP 本来就不是真实的。

像 Disqus 或者其他类似商业服务,虽然这些公司肯定也是可以读取数据的,但正因为有这么一层中间带,它能够让博主不会直接掌握一对一的访客信息。我觉得这很重要。其实这个隐私设计是我不想换到 Waline 或者 Twikoo 的原因之一。另外一个备选项是 Remark42,也是自部署的,在隐私方面就做得好的多。但它需要服务器,如果我买了 VPS 肯定就选它。也可以用 clawcloud 部署,可这个公司我又没那么信任(可能的阿里背景),还怕没几天它就倒闭,真不想再折腾一次了。

二,评论系统的 serverURL 可以在 html 中读取到且直接访问。

理论上任何人可以把这个评论系统添加到任何网页上。只是他们没有管理权限罢了。 后续又研究了下发现可以用 SECURE_DOMAINS 来限制评论。

Twikoo 在这方面则是把前端隐藏了,访问地址只会得到这样的提醒:

{
 "code": 100,
 "message": "Twikoo 云函数运行正常,请参考 https://twikoo.js.org/frontend.html 完成前端的配置",
 "version": "1.6.39"
}

这样有利有弊。Waline 的好处在于可以脱离博客环境直接访问管理系统,回复、删除、编辑评论都在独立网址,避免污染博客访客记录。Twikoo 则是避免了评论系统被他人滥用,但应该就无法独立管理评论(不过我没安装过,不太确定)。

其实想想 GA 和 Disqus 也是类似,shortname 都是暴露在人前的。可能是因为评论系统自部署,风险自担,我就希望它的风险管理可以做得更好点。

另一个控制风险的方法是,所有的邮件提醒都是使用自己邮箱发送,不小心可能就被别人刷爆评论邮箱爆炸。可以在 Vercel 里把 DISABLE_AUTHOR_NOTIFY 设置为 true,这样只有给别人回复时才发邮件,自己收到评论则不会有提醒。有独立的管理系统页面可以访问在这个时候又变成了加分项,只要有浏览器就可以方便查看管理评论。只是我这个小站目前还不至于有这种担心吧,暂时先不禁用好了。

三,Waline 目前无法跨站点共用同一个 backend。

我有两个站点,当时想当然地以为 Waline 可以像 Disqus (Twikoo 是不是也可以?) 一样支持多站点使用。但配置完成之后才发现,不启用邮件通知确实是没什么影响,但一旦开启邮件提醒,SITE_URLSITE_NAME 都只能写在 Vercel 的环境变量里,而不能在前端 init 里定义,这就导致邮件正文想引用 {{site.url}}{{site.name}} 时只能使用 Vercel 里面的值。

我折腾了好久后来想或许可以改动邮件的 Template 设置。翻源码就可以看到默认是下面这样的:

{
"MAIL_SUBJECT": "Your comment on {{site.name | safe}} received a reply",
"MAIL_TEMPLATE": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> Your comment on <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> received a reply </h2>{{parent.nick}}, you wrote: <div style='padding:0 12px 0 12px;margin-top:18px'> <div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> replied:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p><a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>View full reply</a> or visit <a style='text-decoration:none; color:#12addb' href='{{site.url}}' target='_blank'>{{site.name}}</a>.</p><br/> </div></div>",
"MAIL_SUBJECT_ADMIN": "New comment on {{site.name | safe}}",
"MAIL_TEMPLATE_ADMIN": "<div style='border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;'> <h2 style='border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;'> New comment on <a style='text-decoration:none;color: #12ADDB;' href='{{site.url}}' target='_blank'>{{site.name}}</a> </h2> <p><strong>{{self.nick}}</strong> wrote:</p><div style='background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;'>{{self.comment | safe}}</div><p><a style='text-decoration:none; color:#12addb' href='{{site.postUrl}}' target='_blank'>View page</a></p><br/></div>"
}

那么,我可以把前端的 init 里的 path(没有写在 init 里但是这是默认设定)的:

path: window.location.pathname, // unique per page

改成:

path: ' {{ strings.TrimSuffix "/" .Site.BaseURL }} {{ .RelPermalink }} ',

这样就可以保证读取到的 {{site.postUrl}} 是一个完整地址而非相对地址。再取消 Vercel 的 SITE_URLSITE_NAME,然后更改环境变量里的邮件模版,只在回复里体现 {{site.postUrl}} (实则已经是评论的页面完整地址)。

但太麻烦了,我已经筋疲力尽不想尝试。然后我想反正日记站就那么寥寥几个朋友看,就算那个 Disqus 有广告(哪怕是色情广告)反正她们也知道肯定不是我接广告单了,所以自暴自弃就这样吧!真被塞广告了再说。


说出来难以置信,因为换评论系统而生了我自己好大的气。然后又为了生气这件事而生气。

为什么。因为我以为换评论系统只要一个小时,至多两小时就可以结束了吧。实情是什么?加上我写这篇的时间,可能花了十个小时都不止。为什么我要为不重要的事情费这么这么多功夫?为什么我又浪费了自己的时间?为什么别人好像可以很轻松地就完成,我却总是有这么多的问题?(甚至花费了时间还没有解决?)为什么我不能在前期就想好这些需求和做好调查再行动?

甚至,为什么我会为了这些生气?为什么我又为了“生气”本身而生气?

即使把这些全部写下来,我还是没有完全想明白我的脾气从何而来。但明确了一件事,我真的绝对绝对不想再折腾站点功能了!

2025 四月读书记录(一)

2025-09-06 08:00:00

速战速决的四月记录(上)。

想说的当然有很多但翻翻我的欠债(100+),实在是没勇气在这里纠结,赶紧先了结一部分吧。

Mei Li

1939 年凯迪克金奖获奖绘本,以一个中国小女孩儿为主角,这谁能不好奇呢。

在这里可以看到近百年前的北京城,箭楼、城门、马车、驼队,还有旧日刺眼无比的性别观念:男孩儿的世界在外面,而故事的主角 Li Mei,在小小的冒险之后,“Your house is your kingdom and palace”,呵呵,怎能不冷笑。

我的健康厨房

范志红的安全厨房操作手册。

按需阅读,有些卫生观念还是该好好学习一下。

险境奇谈

托尔金的童话、奇幻故事集。虽有不少趣味但还是颇为粉丝向,我不会推荐所有人都读。诗歌部分翻得不够好,但托尔金这种作者想要完全还原他的韵律和节奏本身就极难,我应该会再听一遍英文版。

随机快乐

启发作家的作家们。

大部分作家都不熟悉,不过柳原汉雅和李翊云那两篇真是充分证明我果然不喜欢她们,读不下去她们的作品,连这种短文章都会惹怒我。此外非常想读狄金森!斯蒂芬金的也很不错,计划读他的小说和他关于写作的《写作这回事》。其他被提及的作者倒是几乎没有兴趣。

部分片段非常有意思,回头把摘抄整理一份发出来。

创造自然

五星推荐。

我向来不是名人传记受众,但这本打破了传统的传记叙事,与其说是讲洪堡个人,不如说是借他链接起一整个科学观念、学科研究爆炸式增进的时代。

之后打算再听一遍英文版,到时候有机会再写书评吧。另外可以听自然选择播客的相关节目:当AI困在自我复制里,博物学依旧在观察真实世界

哥伦比亚的蘑菇

儿童教育绘本。无可无不可的读物(对成人来说)。

满是空虚之物

人物形象画得太没辨识度了!分不清谁是谁。故事有点意思。

I Talk Like a River

文本和画面都无可挑剔,兼具情感和美学的表达。也是从这本我开始关注 Sydney Smith 的绘本。

I wake up each morning with the sounds of words all around me.
P for the pine tree outside my bedroom window.
C for the crow in its branches,
M for the moon fading in the morning sky.
I wake up each morning with the sounds of words all around me,
And I can’t say them all.

The P in pine tree grows roots inside my mouth and tangles my tongue.
The C is a crow that sticks in the back of my throat.
The M in moon dusts my lips with magic that makes me only mumble.

河流、森林,一看就非常加拿大。(我对北美部分地貌的熟悉简直让自己也无可奈何,北美出版市场实在是过于强势了。)

I Talk Like a River

感兴趣可以先看 YouTube 上 Ed Sheeran 的朗读版本:I Talk Like A River | Ed Sheeran,也相当不错。

发酵完全指南

两星。

我对自制食品毫无意见,我自己也做过/在做书里提到的相当一部分发酵食物,但问题是,对食品安全只字不提一味鼓吹传统、手工,这就有点可怕了。而其中最严重的就是作者宣称家庭自酿酒不会出现问题,你知不知道一个不小心就会产生甲醇直接人命归西?