碎碎念

陪她去流浪 新建

块编辑器换成 Blocknote 了,AI 风太重了

注意

这篇文章不是用块编辑器写的。

我觉得功能太简单了,无法写出复杂内容的页面。对于我自己来说,不如手写舒服。
集成此功能的主要目的是多样化支持(免费代码越写越死),后续还想支持 Typst: Compose papers faster

总共花了两天时间:看文档,学 React 框架,最终差强人意地集成进来了,代码改动其实很少,主要时间在学习各种东西。

那还是说几个不好体验吧:

  1. LOGO 的这种蓝紫色风格太 AI 了。有一种 Vibe Coding 的感觉,有点不适。
  2. 很难自定义,文档看起来很多,其实可用内容很少。而且部分内容需升级成 Pro 才能看。
    1. 很多组件没有文档。比如 Image,得靠从文档结构反推用法。
    2. Image 组件如何重写上传UI”不给看,难以自定义。
  3. 会允许一些不规范的内容存在:
    1. 允许段落内出来列表。见:BlockNote - Tables。HTML 规范是不允许 <p> 内出现 <ul> 的。

文档结构(Document Structure)没有明确的规范文档,只能从实践反推规范。从“文档结构”到“HTML”的渲染过程是我自己手写的。只能做到尽量兼容。

对表格的编辑体验比较满意,勉强算比较接近 Confluence 的编辑体验了。

测试用 Blocknote 编写的文章:《测试 Blocknote 块编辑器》。

没有评论 页首

测试 Blocknote 块编辑器

[{"id":"ee3b6b4a-4860-4dc6-ae0f-c1d51cdd1f3d","type":"heading","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","level":1,"isToggleable":false},"content":[{"type":"text","text":"测试 Blocknote 块编辑器","styles":{}}],"children":[]},{"id":"4b2ae4c1-ba89-41ee-bd62-05b53b4fbbc6","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"注:","styles":{"bold":true}},{"type":"text","text":"这篇文章是用 ","styles":{}},{"type":"text","text":"Blocknote","styles":{"italic":true}},{"type":"text","text":" 而非 ","styles":{}},{"type":"text","text":"Markdown","styles":{"italic":true,"strike":true}},{"type":"text","text":" 编写的,用于测试 Blocknote 的集成及各项功能。","styles":{}}],"children":[]},{"id":"c883ab27-fab7-460d-9e95-a6d704e206f9","type":"quote","props":{"textColor":"default","backgroundColor":"default"},"content":[{"type":"text","text":"这里显示一段引用文本。","styles":{}}],"children":[]},{"id":"47404122-bd80-43e3-8aa6-9927d40ab213","type":"toggleListItem","props":{"textColor":"default","backgroundColor":"default"},"content":[{"type":"text","text":"这里是可折叠列表。","styles":{}}],"children":[{"id":"e830c311-ab0e-4789-a279-5b0f943ab357","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"这里是被折叠/隐藏的内容。","styles":{}}],"children":[]}]},{"id":"b225d7c7-78de-4b6e-9994-885f0ef14b22","type":"numberedListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"111","styles":{}}],"children":[]},{"id":"0bf5a90f-f4fd-49cb-9ba6-be753dfc14a0","type":"numberedListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"222","styles":{}}],"children":[{"id":"8a69828c-5ad2-4562-8080-10894b6cf2a4","type":"bulletListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"111","styles":{}}],"children":[]},{"id":"1e228986-e218-469e-964c-0b86114c0eda","type":"bulletListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"222","styles":{}}],"children":[]}]},{"id":"31c634fd-be73-482d-be40-4f3f373aac77","type":"numberedListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"333","styles":{}}],"children":[]},{"id":"b49ee4f0-a09a-4e27-bc41-8bf7c62afe33","type":"checkListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","checked":true},"content":[{"type":"text","text":"待办事项1","styles":{}}],"children":[]},{"id":"00246947-33ed-466f-b0de-aa5463b3afe2","type":"checkListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","checked":false},"content":[{"type":"text","text":"待办事项2","styles":{}}],"children":[{"id":"4ba1cc45-6df1-4a96-8eff-01949aafa76e","type":"checkListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","checked":false},"content":[{"type":"text","text":"待办事项3","styles":{}}],"children":[]}]},{"id":"c7b1bbcf-fba4-4b43-9bae-d57430437f6a","type":"codeBlock","props":{"language":"text"},"content":[{"type":"text","text":"// You can edit this code!\n// Click here and start typing.\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, 世界\")\n}","styles":{}}],"children":[]},{"id":"81defc19-7cad-4be4-a5e8-8c28b83c2695","type":"table","props":{"textColor":"default"},"content":{"type":"tableContent","columnWidths":[199,148,201],"headerRows":1,"rows":[{"cells":[{"type":"tableCell","content":[{"type":"text","text":"This row has headers","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"default","textColor":"default","textAlignment":"center"}},{"type":"tableCell","content":[{"type":"text","text":"This is ","styles":{}},{"type":"text","text":"RED","styles":{"bold":true}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"red","textColor":"default","textAlignment":"center"}},{"type":"tableCell","content":[{"type":"text","text":"Text is Blue","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"default","textColor":"blue","textAlignment":"center"}}]},{"cells":[{"type":"tableCell","content":[{"type":"text","text":"This spans 2 columns\nand 2 rows","styles":{}}],"props":{"colspan":2,"rowspan":2,"backgroundColor":"yellow","textColor":"default","textAlignment":"left"}},{"type":"tableCell","content":[{"type":"text","text":"Sooo many features","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"gray","textColor":"default","textAlignment":"left"}}]},{"cells":[{"type":"tableCell","content":[{"type":"text","text":"aaa","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"gray","textColor":"purple","textAlignment":"left"}}]},{"cells":[{"type":"tableCell","content":[{"type":"text","text":"A cell","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"default","textColor":"default","textAlignment":"left"}},{"type":"tableCell","content":[{"type":"text","text":"Another Cell","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"default","textColor":"default","textAlignment":"right"}},{"type":"tableCell","content":[{"type":"text","text":"Aligned center","styles":{}}],"props":{"colspan":1,"rowspan":1,"backgroundColor":"default","textColor":"default","textAlignment":"center"}}]}]},"children":[]},{"id":"027dc5ff-db8e-4792-a9b6-5332ae72e363","type":"image","props":{"backgroundColor":"default","textAlignment":"center","name":"","url":"四姑娘山.avif","caption":"","showPreview":true},"children":[]},{"id":"3d62a8ab-679e-40ee-8474-9f7e6f64894b","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]},{"id":"503ac523-f490-4884-b36a-bfa9d589fc85","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]}]
没有评论 页首

QQ 居然暴露了通过 QQ 号直接获取头像的接口

依稀记得很多年前就被禁止了,没想到在逛网站《关于建立blog的第一篇文章👻 - 李欲裕》的时候发现居然能通过 QQ 号直接获取头像:

我的头像:https://q.qlogo.cn/headimg_dl?dst_uin=191035066&spec=4

spec 参数看起来是用来配置图片大小,测试了一下 5 是高清图。

又可以加个 TODO 了,虽然不一定会做:

  • 增加通过 QQ 号获取评论者头像并显示

但是链接中不能包含QQ号以防止隐私泄露。上述网站是可以直接看到 QQ 号码的,有点不注重隐私。

没有评论 页首

尝试给文章加个可视化编辑器,Editor.js 让我很难受

我一直不想给博客文章编辑器加“更好用的”/可视化编辑器的一大主要原因就是:真的不好用/不如手写。

今天尝试了一下 Editor.js,说说我遇到哪几个不能忍的小问题:

  1. “Clean JSON Output” 并不 Clean

    段落内带加粗的文本“aaa bbb ccc”实际生成的是:

    1
    
    aaa <b>bbb</b> ccc
    

    你跟我说这叫 clean?

    我以为是我的用法有问题,结果看了官方的例子也是如此。

  2. 行内格式化工具应用后无法取消

    比如:给末尾的文本应用加粗/代码等格式后,后续所有的文本都会自动应用此格式且无法取消也无法再插入普通文本。

    说起来有点空洞,看视频吧:

    可能的解决办法是:输入一段普通文本,再把它取消为代码。太离谱的操作了。

难受,怎一个难受了得!写点东西手来来回回地切换来切换去,是要急死我。

2025-7-30 19:04:51

太离谱了,看了《The WHATWG Blog — The Road to HTML 5: contentEditable》这篇文章:

  1. contentEditable 居然是 IE 发明的,而且版本是 5.5 (2000年的时候)。IE 居然这么前卫。

  2. 现代 HTML5 里面的等同物居然是通过逆向工程抄袭 IE 并成为规范的。

    天杀的,微软作为 HTML 标准成员之一居然不舍得开放一下实现?不知道是该夸还是该骂。

2025-7-30 19:35:24

想起刚刚往表格里面插入了一张图,然后准备试试网上找到的各种编辑器是否支持插图到表格。结果是:均不支持。

看起来我还是得继续手写。是不是呢、是不是呢!

表格也不支持拖动表头。

所以,看起来我要么是完全手写,要么就上一个“全功能的”编辑器。

没有评论 页首

为什么 Steam 总是一打开就卡死?

为什么为什么?你知道你旁边就是垃圾桶🗑️吗?

就连 BugReport 程序也能转菊花🌼️,你去死好吗?

2条评论 页首

注册了个 X/Twitter 的免费开发者账号,还不知道要干什么

很早以前就想注册,但那时候不免费、不便宜,而且好像很容易被回收,所以一直搁置。

今天看到有人说 X 的 API 很好注册,于是我就又尝试了一下。居然……没有审核,秒过。

接下来是思考一下能做点儿啥?也许,能同步碎碎念和推特?

每个月能免费拥有:500次写入、100次读取。

没有评论 页首

把前司最后一件装备卸下了

没有评论 页首

坑爹茶杯头(CupHead)打得我奶痛

觉得普通模式实在太难了,所以我一直打的简单模式。这样也可以通关所有墨池岛/世界,并进入终章。

但是,直到进入终章的时候才告诉我没有拿到所有的灵魂契约(简单模式拿不到,前面只有方框,没有打勾✅️),害得我又得重新跑回去把所有 BOSS 重新打一遍……🤬🤬🤬🤬🤬。坑爹茶杯头毁我青春。

2025-8-16 07:19:23

终于拿到了所有的灵魂契约,但是已经死亡了 1200+ 次。

2025-8-21 15:19:51

好的,总算是打完了魔鬼。出现了专家模式,但是已经没有耐心再打了。

10-4-2025, 1:15:34 PM

耐性恢复了,购买了 DLC 内容,把盐大厨也打通关了。

最搞笑的是,居然唯一一个评分为 A 的章节竟然是最后一节!

2条评论 页首

拖了一个多月,终于还是把车险给上了

从六月初到现在七月底,虽然隔一差二地微信➕电话轰炸,但是没有回过一条消息、没有接过一次电话。直到今天脱保第 4 天。

费用从 ¥3800+ 降到了 ¥3200+,看了一眼列出来的各种险种,好像没有奇怪的东西,然后就还是乖乖地交了钱。说起来还是有点担心车子的,一年两箱油就这样把车放在农村被大太阳晒着🥵。

交完之后去问了一下我姐她的车(比我晚买半年)费用是多少,好家伙,¥2900,还返现了 ¥200. 我是傻逼🐷️。

有时候就在想,车™️真是个纯消费品啊,无任何收益。每天贬值,还要每个月几百的保险费用、停车费用。

没有评论 页首

无印良品 ≠ MUJI无印良品

对象说最近购买的无印良品被子怎么这么便宜:

这不,我就刷到了一条视频:

还是中国商家牛逼啊。连我自己也差点忘记了,以前确实是知道这个事情的。😑

没有评论 页首

在深圳也能吃到重庆楼下的“池中吃老火锅🍲”了

连个注册®️商标都没有,一定很地道![doge]

2025-7-27 11:46:17

以及,买了一个小火锅灶:

没有评论 页首

简直就是灭蟑螂🪳神器

名字叫:呋虫胺。只管按照 1:100 的比例往地上喷一遍,待会儿等着捡尸就行了。无色、无味、无毒(对哺乳动物而言)。比传统常见的喷雾方式效果好很多!

除了“双马尾”外,蟑螂🪳居然还有另外一个名字:蜚蠊!

没有评论 页首

孤帆远航⛵️(Far: Lone Sails)通关了

世界末日,只剩一个人、一辆车,不停地在沿途拾荒并作为燃料。引擎开关会自动断开,需要不断地开启。狗屁通:你看起来很忙吗?那就对了!终点是大海,车辆已经无法前行。但配有一处灯塔,也许是象征向远方呼救。

一开始玩不懂,觉得无聊。查了攻略,玩法没错,果然无聊。我不是特别喜欢这类游戏。节奏太慢了!而且剧情玩法略显简单。

没有评论 页首

快进来看女装大佬!

不会吧?不会吧!

实况
实况
6条评论 页首

Limbo(地狱边境)通关了

结局是个小女孩👧🏻️,感觉并不地狱……?

反而是剧情中有一些情节比较血腥,实在阴森。

2025-7-23 00:17:04

看到了游戏信息:

姐姐命运不明,男孩进入了命运边境

没有评论 页首

Gris 通关了,很漂亮

没有评论 页首

BitTorrent 竟然还可以聊天?

如图所示1

不过我没有很惊讶,毕竟 BitTorrent 是非常经典的 P2P 协议。

想起当年自己也写过小巧能用的 BitTorrent 客户端实现。

那还是在实现之前几年,我就粗略翻看过 BitTorrent 协议,仅一页,非常精练(见 bep_0003.rst_post)。当时觉得非常神奇,被无数人使用的 BT 软件协议竟然如此简单?我完全不敢相信。后来直到真的自己实现了一个2才发现,确实很简单。 也许是我的第一个完整的 UDP 应用。

本文的协议特指原始的 BitTorrent P2P 协议,不包含类似 DHT(分页式哈希表)增强协议。

没有评论 页首

这年头,硬盘价格也水涨船高了😕

2023 年 4 月份买第一张盘(希捷)的时候1才 ¥1580,大概 ¥100/TB。大概是随着最近大语言模型的需求,硬盘这涨得也太离谱了……

原来的价格只有大客户才能买到了。这是淘宝,而京东更贵。不买了。

所有数据目前只有独立一份备份,丢了就永久没了。

2025-8-14 01:07:31

不好,被对象看到后愉愉给我买了一块😭️。

1条评论 页首

拿 Scriptable 写了个脚本并作为小组件显示网站备份状态

网站搭建在厂商那边,随时都有可能跑路的风险,所以数据安全是重中之重。目前的备份策略是每小时一备份,一天下来,能收到超过 20 条备份成功的消息。感觉有点“罗嗦”,甚至不胜其“烦”把成功通知默认静音了。但是仍然避免不了需要不定期清理这些不重要的、大量的“成功”通知消息。

所以干脆把通知给停掉了,然后用 Scriptable1 给写了一个手机桌面小组件。

结果像下面这样(界面是随便写的,并不漂亮,够用就行):

把它放在手机主屏幕上,偶尔看看就好。如果没看到,问题也不大,因为失败时总是会有即时通知消息的。

代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
let info = await new Request("https://blog.twofei.com/v3/info").loadJSON()
let widget = new ListWidget()

let stack = widget.addStack()
stack.addText("备份:")
let date = stack.addDate(new Date(info.last_backup_at*1000))
date.applyOffsetStyle()

stack = widget.addStack()
stack.addText("同步:")
date = stack.addDate(new Date(info.last_sync_at*1000))
date.applyOffsetStyle()

widget.presentSmall()

  1. 本来是准备用快捷指令实现的,那玩意儿实在有点功能少、写起来麻烦,于是放弃。 ^

2条评论 页首

接着玩《双影奇境(Split Fiction)》

本来是准备买个 Nintendo Switch 1/2 或者 PS5 的,结果发现性价比都很低。或者游戏超级贵,比如 PS 上的游戏普遍好几百,肉痛。所以还是玩 Steam/蒸汽机 好了🙂‍↔️,经常打折,多好。现在正值夏季,一口气买了数十个游戏。

刚在电玩城玩完1《双人成行》,发现《双影奇境》是其续作,也准备玩一下。看了一眼 Steam 上居然有 ¥200 左右,实在不舍得,然后就在小红书偶然刷到 ¥8 块钱盗版🥵,没忍住、花巨资买了。

这玩意儿竟然有足足 80GB 大小,可能算是有史以来安装过的最大的一个 App 了2,实在另人恐怖😱️。

好奇研究了一下这个 App 的内容,神奇地发现它居然有好几层模拟环境:

  1. 在 M 系列 MacOS 上用 Rosetta 模拟运行 Intel 指令集;
  2. 在 Intel 上运行 Wine;
  3. Wine 运行 Windows 虚拟机;
  4. Windows 虚拟机运行 双影奇境.exe;

离谱,这性能能好到哪里去?那叫一个卡。好在我把几乎所有特效都关闭/调到最低了,除了抗锯齿外(实在没法看)。整体还算流畅,偶尔卡顿。

内存占用实在是很高:

随便贴几张截图。

很好看的丛林:

很有赛博朋克风格的都市🏙️(视频压缩过,原视频清晰好看得多):

超级搞笑的骑摩托🏍️输验证码片段:爆炸💥️倒计时中,输不对验证码🥵🥵🥵,屁股冒火🔥️(原视频 280MB,压缩成了 7MB,画质很堪忧):

没有评论 页首

买了两个手柄🕹️,没日、没夜地玩起 Steam 了

说明书1 说明书2

2025-11-02 19:35:22

不好,下面这个便宜货(< ¥100)已经坏了(左手摇杆响应迟钝)。已于今天退货。

2025-11-06 23:07:29

没退货,换了个新的。

2025-12-11 17:07:23

最近不打游戏,准备收藏起来,每半年充一次电?

给手柄充电🕹️
203
开始时间:2025-12-11
2条评论 页首

又是被狗屁通气死的一天:“国行”怎么读?

“国行”是什么意思。


国行”是“中国大陆官方行货”的简称,意思是:

由官方正规渠道在中国大陆销售、认证、发行的产品。


怎么发音。


国行”的发音是:

拼音:guó xíng

  • (guó) → 第二声
  • (xíng) → 第二声(在这里读作“行走”的“行”,不是“银行”的“háng”)

📢 朗读起来像:

“国行(guó xíng)” = guó xíng

🗣️ 类似于你在说:“国家运行” 的“国” + “行走”的“行”。


⚠️ 注意:

  • “行”在不同词中读音不同,比如:
    • 银行(háng)
    • 行走(xíng)
    • 行不行(xíng)

在“国行”中,它读作 xíng(第二声)。


它不是“行货”的简称吗,为什么不念hang


你问得非常好!“国行”确实是“国产行货”的简称,其中的“”来源于“行货”,所以从这个角度讲,很多人认为它应该读作 háng —— 这是很合理的。


✅ 正确读音是:guó háng(国行)

读音 含义
guó 国家
háng 商行、商品流通的意思(例如“行货”、“银行”)

📌 为什么不是“xíng”?

  • “行”这个字有多个读音:
    • háng:用于“行业”“银行”“行货”等,表示商业机构
    • xíng:用于“行走”“进行”等,表示动作

✅ 所以在“国行”=“国(产)行(货)”中,“行”确实是“háng”


🧠 为什么会有人读成“guó xíng”?

主要是因为:

  1. “行”这个字太多音了,日常说话时混淆很常见。
  2. 有些人误认为是“国家发行”或“国家运行”的意思,才会误读成“guó xíng”。
  3. 很多媒体和电商平台没有明确标注拼音,大家都是照着猜。

📚 正确例句:

  • 这台 iPhone 是 国行(guó háng),有三年保修。
  • 水货比 国行 便宜,但没有售后服务。

✅ 总结:

拼写 正确读音 意思
国行 guó háng 中国大陆官方销售的正规版本
❌ guó xíng 错误读法 多数是误解或口误造成的

我你妈……🤬🤬🤬🤬🤬🤬🤬。

2条评论 页首

mXSS:好像兴趣不大,快点攻击我啊

看了火狐最近的大版本更新记录,说是在序列化 HTML 特性(Attributes)的时候会转义 <> 以防止 mXSS 攻击了:

Firefox will now escape less-than (<) and greater-than (>) symbols when serializing HTML attributes, making certain mXSS attacks on websites more difficult.

不知道 mXSS 是啥玩意儿,于是去了解了一下:《mXSS: The Vulnerability Hiding in Your Code | Sonar》。大意其实就是:出于浏览器对 HTML 标签的兼容性解析策略,可能会出现手写的 HTML 和实际得到的 DOM 树不预期。即浏览器会出现各种自动调整 DOM 树构建顺序的决策,进而导致跨站脚本攻击。这种“自动调整”就被称作“Mutation(mutation cross-site scripting)”。具体看上述文章的例子就很好(比如把双引号内的“</style>”也解析成标签的一部分)。

自我感觉这种情况对我来说风险不大,出现的可能性较小,所以暂时不处理。希望有兴趣的人士来攻击一下我,给我网站挂马。让我找到我自己的薄弱点。

我的网页几乎全部是 Go 的模板生成的,之前也不是没有出现过拼出的最终 HTML 页面出现过标签错误。也想过把W3C Markup Validation Service集成到端到端测试环境中,这样就基本能杜绝这种情况。后来一想到我有点谨小慎微了,就尚且没有这样做。

2条评论 页首

安全回到深圳了,感谢南航

实况

第一次坐到有充电口的飞机!而且是 Type-C,超棒,终于不显得那么格格不入了。不过,虽然起飞时不让使用,但是为什么不直接从总控切断电源,而是一个个地检查并让拔掉❓

也是第一次用卫星图层导航,发现看起来比平面地图好看很多!

https://x.com/whyyoutouzhele/status/1940323264712102378

没有评论 页首

第一次接到“国家反诈中心”电话

当然,我不会、也没有接这种无聊的电话,即便对方打了几次。

不知道有无关联:差不多一个小时前,我打电话预约了“无为寺”的免费斋饭,对方要求我把姓名和电话号码通过短信的方式发了过去。

没有评论 页首

新技能 GET —— 您身边的采耳大师已上线

实况
没有评论 页首

看着没有一个 3C 标识的大疆设备的我不仅陷入了沉思……

3条评论 页首

离开学校已经十年?

好快好快!

2条评论 页首