碎碎念

陪她去流浪 新建

《Using i.e. and e.g. correctly》1

The abbreviation “i.e.” stands for id est, which is Latin for “that is.”
The abbreviation “e.g.” stands for the Latin phrase exempli gratia, meaning “for example.”


哇,国外的正规引号的写法真的就是中文的引号!?

“
LEFT DOUBLE QUOTATION MARK
Unicode: U+201C,UTF-8: E2 80 9C

分号是这么用的:

All employees will receive the standard discount; i.e., 20 percent.

...we technically have created a compound sentence...
So we use a semicolon to join the two independent clauses.

没有评论 页首

用过 Unix-like 系统的人都知道以 “/” 开头的路径是绝对路径,但是不知道 Go 为什么要加一个奇怪的 URL.IsAbs() 函数,这个函数只通过判断有没有协议头(Scheme)来确定是不是绝对路径……

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
	"fmt"
	"net/url"
)

func main() {
	u1, _ := url.Parse("/1.txt")
	u2, _ := url.Parse("file:///1.txt")
	fmt.Println(u1.IsAbs(), u2.IsAbs())
}

你要这么搞的话,我感觉 Go 语言对我来说有点儿不受控了……

1
2
$ go run main.go
false true

就算对于前端来说,以 / 开头的也是绝对路径啊,以 https:// 开头这种难道不叫跨源吗?都可以叫作“不是同一个文件系统”了……

没有评论 页首

今天的海湾红树林公园

实况
实况
实况
没有评论 页首

笑死,神经病一样,在 GitHub 上看故事1,这些烂用 GitHub 的人到底有没有公德心? #王思聪 #AVIF

又不回我是吧.jpg

特意贴这句话,是突地想起了前司的一位同组的女同事……之前经常相互发这个来着……🥵,差点遗忘,写下来,对抗遗忘。

为了防止我自己也忘记名字,我应该把名字记录在本文中,怎么做?

6条评论 页首

这是一条来自手机端 iOS App 的碎碎念!🍏🍎。 测试!

人生 #第二次 开发 iOS App!

当然,我并不是要开发一个完整的客户端,只是为了测试一下如何在 iOS 上使用 #GRPC#ProtocolBuffer,上手难易程度完全在预期范围内,感觉当初用 GRPC + ProtocolBuffer 重构 API 接口是非常正确的选择。

只是……接近两年没写 #SwiftUI 了,反倒是 UI 慢慢摸索了好久……

2024-6-2 09:18:11

(当然,图片不是来自手机端 🤪🤪🤪)。

2024-6-2 09:34:19

我一定是现学现用!感觉从来没有开过这么多的标签页!

#第一次 使用 #AVIF 图片格式,比 JPG/PNG 都小,甚至比 WebP 还小很多,后面有空再试试 #JpegXL

第一次总有些不愉快…… 是的,下面这张图好大,因为我代码的图片自动缩放功能不认识 AVIF 格式,晚点有空再修吧😇

tabs.avif

2024-6-2 23:51:10

暴力出奇迹:java - How to get image dimensions from an avif file? - Stack Overflow

LMt5R.jpg

2024-6-3 07:43:51

#AVIF 图片大小修好了,就不会有我搞不定的事!

2024-6-14 18:01:58
2条评论 页首

找了半天的图片转文字(OCR),要么是收费昂贵、要么是安装复杂、要么是识别效果差、要么是中文不友好……

咋的,是家里手上花几万块钱买的 MacBook Pro M2 32G 它不香吗?🤔

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//
//  main.swift
//  ocr
//
//  Created by Yang Tao on 2024/5/31.
//
import Foundation
import Vision

func recognizeText(_ path :String, completion: @escaping ([String]) -> Void) async {
	let handler = VNImageRequestHandler(url: URL(fileURLWithPath: path, isDirectory: false))
	let request = VNRecognizeTextRequest { request, error in
		let result = request.results as! [VNRecognizedTextObservation]
		let results = result.compactMap { $0.topCandidates(1).first?.string }
		DispatchQueue.global().async { completion(results) }
	}

	request.recognitionLevel = .accurate
	request.recognitionLanguages = ["zh-CN"]
	
	do {
		try handler.perform([request])
	} catch {
		fatalError(error.localizedDescription)
	}
}

let path = CommandLine.arguments[1]
await recognizeText(path) { $0.forEach { print($0) } }

就这加上空行、注释才 29 行 Swift 代码,要什么自行车🚴?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ocr (master) → swiftc main.swift 
ocr (master) → ls
main       main.swift
ocr (master) → ./main ~/Downloads/IMG_9598.jpg 
照片墙
14 关注
杨晚晚
C
) VIP 伍
2229粉丝
网易音乐人、歌手
IP 属地 湖北
互相关注
聊天
ocr (master) → ./main ~/Downloads/IMG_9601.JPG 
18
+ 添加状态
)VIP•伍
“我在江南君在北,一片痴情空与对。”
010枚徽章|广东 深圳•o 90后 摩羯座•村龄7年
32关注
2粉丝
Lv.8等级
1953时听歌
L 最近
v本地
^ 云盘
已购

不好意思,这里也是 29 行,就是这么巧!

图片来自上一篇碎碎念

2024-6-3 10:03:25

开个坑:

  • 博客支持自动识别图片文字内容并保存、可供文本搜索图片🔍。

    可选方案:服务在后台扫描有更新的文章,通过 grpc stream 的方式让提供方(本地客户端)提供技术支持。

没有评论 页首

从上一份外企的工作的经验得知,#日历 这个东西,也知道像是手机上的日历、#待办事项#备忘录 一样,都是有通用的标准的。像是 Apple、Google 都在使用这些古早的标准。是的,非常古早,无它——任何除 HTML 外仍在使用 XML 作为交换数据格式的协议我都认为是古董了。

这也使我极度排斥和它们打交道,之前做 XmlRpc/Pingback 把我做到吐。所以虽然我一直想做一个自己的日历本,一直拖、一直拖…… 在拖到完成之前,这条碎碎念我就慢慢 #填坑 吧。

2024-5-31 02:42:14

Tokidoki,是 go-webdav 作者的项目,前者基于后者,实现了基于文件系统的后端。目前看起来还比较粗糙,还不足以上生产环境。

  • 现实一个基于 SQLite3 的后端,和博客程序集成(作者正在实现基本 PostgreSQL 的后端);

iCalendar 的一些坑

  • 全天事件不包含结束日期在内;非全天事件包含结束时间点。
  • 参与人必须要有邮箱地址,不能只填姓名。
  • 苹果的日历不支持 GEO,然后填 LOCATION(位置的名字)的话,地图上会任意显示一个匹配的位置,屎一样);可以考虑使用 X-APPLE-STRUCTURED-LOCATION
没有评论 页首

害怕,好久没上 #网易云音乐,竟然发现被 #杨晚晚 关注了……🥵🥵🥵

吓得我赶紧改了个签名✍️……你猜我为什么被关注?😎😎😎

2024-5-30 15:08:54

必须来一首 #洗脑 的歌:

标题:片片相思赋予谁

专辑:片片相思赋予谁

作者:杨晚晚

00:00

我是不是年纪大了,为什么觉得这种歌听起来很带劲?🤔

2024-6-14 19:25:42

reply.avif

(好像让大家看到我名字了👀。)

4条评论 页首

<script> 嵌入 JSON 的正规做法1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- Generated by the server -->
<script id="data" type="application/json">
  {
    "userId": 1234,
    "userName": "Maria Cruz",
    "memberSince": "2000-01-01T00:00:00.000Z"
  }
</script>

<!-- Static -->
<script>
  const userInfo = JSON.parse(document.getElementById("data").text);
  console.log("User information: %o", userInfo);
</script>
2024-6-14 04:21:43

实际上,放 Yaml 也不是不行,就像我友链文章中的那样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!--article begins here-->
<script type="application/yaml">
friends:
- name: 小竹の笔记本
  url: https://notes.smallbamboo.cn
  description: 这里是编程宇宙中一颗璀璨的星辰,照亮你探索知识的旅程。
  icon: https://notes.smallbamboo.cn/wp-content/uploads/2024/04/1714049480-icon.png
- name: Doghouse
  url: https://qwq.me/
  description: In the Mood for Love.
- name: 卡瓦邦噶!
  url: https://www.kawabangga.com/
  description: 无法自制的人得不到自由。
...
没有评论 页首

在 StackOverflow 上面发个帖子问一下关于 Safari 字体大小问题 的根本原因时为了补充一个视频时发现:StackOverflow 支持 GIF,但是不支持 MP4.

可是……当我用 #FFMPEG 把录屏转换成 GIF 时:

1
2
3
4
1.6M a.mov // 原始录屏
200K a.mp4 // ffmpeg -i a.mov a.mp4
1.3M a.gif // ffmpeg -i a.mp4 a.gif
1.0M b.gif // ffmpeg -i a.mov b.gif

转了一圈最后发现,GIF 不管是大小、清晰度、帧率、声音通道、色彩空间都完全被 MP4 吊打啊,完全不在一个量级。

这还是我读高中时认识的那个占用空间大的 MP4 格式吗?StackOverflow 这样抱残守缺干嘛?连 Twitter 都早就用 MP4 代替 GIF 了。

放个 MP4 吧(GIF 就不放了,感觉浪费我空间😅),200KB,8 秒的视频,如此清晰,什么如获至宝,时代的眼泪……

2024-5-29 19:56:01

哈哈哈,在别人的网站上又看到了一个 GIF。是功夫里面的冯小刚打人片段,我从原视频里面截了一部分,然后转成了 MP4,大小为 179KB,原 GIF 是 362KB,仅是后者的 50%,且不说 MP4 的分辨率是 GIF 的 两倍……

kf.gif
实况

GIF 看着好有年代感啊!一看就回到了那个年代。

没有评论 页首

自以为是早期的 Win32 开发者,对事件系统非常熟悉,以为可以照搬到浏览器里面。尽管如此,但还是在 js 这里踩了坑,对浏览器中 js 执行顺序误解很大。

比如下面这些代码片段,打印顺序是啥样?

1
2
3
<img src="bad://" onerror="alert('111')" />
<script src="not-found.js"></script>
<script> alert(333); </script>

其中,not-found.js 是一个不存在的脚本。

测试用例:first.html

然后再看看下面这个:

1
2
3
<img src="bad://" onerror="alert('111')" />
<script src="222.js"></script>
<script> alert(333); </script>

其中,222.js 的内容是 alert(222);

测试用例:second.html,记得多刷新几次看看有没有不同。

以及:

1
2
3
<script src="222.js"></script>
<img src="bad://" onerror="alert('111')" />
<script> alert(333); </script>

测试用例:third.html

别问我,我不知道。

没有评论 页首

七娘山⛰️真是个特殊的山,特殊在哪呢,就是能不能去登山完全取决于当天的天气,对,是当天。因此,需要当天打电话问管理人员才能决定,官方(深圳大鹏半岛国家地质公园)并不会在任何地方公布这个信息(微信公众号已经停留在了几年前)。也别相信各个地图所谓的“正在营业”,因为我上次去就扑空了,然后转去了隔壁的杨梅坑/鹿嘴山庄。

没有评论 页首

2024-05-26.md

待办事项

没有评论 页首

合法的新手司机了,周年快乐!

license.jpeg
stat

这里程中,90% 应该都是我贡献的,高速应该超过 50%.

如果不是因为保险限制一年不能超过 30000 公里,这数据再翻过倍毫无压力。


#仪式感 ,是的,晚上又去吃椰汁鸡了!不过,这次变得有些“聪明”了,竟然想起了问老板有没有停车🅿️券,有!感觉以前血亏!那可是深圳超繁忙路段之一啊!


上次买 #宝马 的那个朋友,跟妹子的关系似乎发展不如预期,找我吃了个夜宵。结论:现在的妹子真的难追……尽管他已经差不多年薪百万的深圳人了,还是感觉难,非常地难。不知道现在的妹子在想什么……噢,忘了说,他把上次在光明买的宝马订单退了,等等,不是不买了,是换成了一家南山的店,价钱一样,赠品也几乎完全一样,除了我当时坚持的座椅通风。他说:天热怕什么,空调给我使劲开!

2条评论 页首

一直用 @media screen,今天才知道有 @container 这么个神器,简单一图胜千言:

container-query.svg

没有评论 页首

2024-05-22.md

待办事项

  • 服务端和客户端版本必须match
  • 获取 4K 图片 https://pbs.twimg.com/media/GA0Qq0DbYAEltfQ.jpg?name=4096x4096
  • 同步评论中代码的滚动
  • 邮件中的 # 评论 hash 不见了
  • 关于 <template> 被 parse 进 head
  • 保留原始 markdown 中的 html 注释。
  • 播放器适配移动端
  • 搜索功能换成 ListPosts
  • 不设置语言的代码块格式乱了。
没有评论 页首

把推特的数据📊从官方轻松点几下、一键导出了,非常便捷。只不过,官方说为了安全,需要等待至少1️⃣天时间才能下载,期间会不停地要求邮件验证以确定帐号安全。

刚好满一天,下载了下来,打开一看,非常吃惊😱。打开首页,完全就是个离线版的推特,有自己的全量数据,一览到底,所有文字、图片、视频打包📦在一起。各种数据文件的格式在文档中描述得清清楚楚。

什么业界良心企业啊,我哭死……😭

我……是不是要导入过来呢?

5条评论 页首

早前推上有人说像 Markdown 这种简单的文档可以用正则表达式很轻易地解析,我完全不以为然,因为我自己用正规的递归下降解析写过,发现……挺 tricky 的。但是在《网站支持 Live Photo 图片展示》上发现我很久很久之前用过的 marked 这个 js 写的 Markdown 库竟然就是用的正则表达式实现的?

我低估了正则表达式的强大,也低估了作者们的能力。但是有句关于正则表达式的话我还记得很清楚:

Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems. (Source of the famous “Now you have two problems” quote)

很多人写的正则,是那种写的时候看得懂,事后就忘记。不然你看看下面这段装逼过度

1
R"((\w+)\s+([^\?\s]+(\?(\w+(=(\w+)?)?)?(&(\w+(=\w+)?))*))\s+(.*)\r?\n(([-\w]+\s*:\s*.*?\s*\r?\n)+)\r?\n)"

我只敢肯定这段代码是我给公司写的,语言是 C++,但是意义嘛……

但不管怎样,我最终还是放弃了marked,因为我不想在后端一直保留 nodejs,我是🐶党。

2条评论 页首

随机 #开往 了一个网站“Evan's Space”,发现作者把文章的附件挂在国内某云盘上,尽管附件仅有 8KB 大小……

说实话,作为一个经历过中国互联网大大小小在线存储、云盘服务商的我来说,不是很理解这种行为。

一些不成熟的见解:

  • 写文章✍️时单独上传附件到站外是一个麻烦事(可能有插件集成);
  • 云盘文件可能被莫名其妙地和谐、丢失、删除、不可用;
  • 不方便自己整理数据、备份数据;
  • 云盘可能下载速度还没自己的小水管快;
  • 云盘可能强制用户下载 App 后下载;
  • 云服务商的链接可能挂掉;
  • 云盘服务商可能没自己的网站活得久;
  • 云盘跑路,自己的数据全部丢失。
  • ……

所以,我从建站初期就很少使用过第三方存储(云盘、图床等)。尽管前些年用过腾讯云 COS 存储我的音视频(太大了以至于我不想放 Git 仓库),直到后来腾讯云换域名(以及改 HTTPS 访问)导致之前的链接挂掉了之后,我就弃用了。我认为他们对兼容性的考虑甚至比我更加草台班子。

3条评论 页首

2024-05-20.md

待办事项

  • 通过 img loaderror 的方式执行同步滚动注入脚本。
  • 只保留三栏,合并评论
  • 启用标签插件
  • 把 plantuml 插件独立并开放
  • 用公钥代替 token 加密,携带时间。
  • 用 plantuml 的 mind 功能展示博客功能集。
没有评论 页首

2024-05-19.md

待办事项

  • 写一个类似日历的事件记录系统,比如十周年
没有评论 页首

为了给博客后台的碎碎念找个能用的 Markdown 编辑✍️器,结果一不小心给人家提了一堆 issues,感觉我有罪:

tme.jpg

选此 Tiny-Markdown-Editor(TME) 的原因有几个:

  • 足够小巧、简单,算是一个小而美的产品(除兼容性 Bugs 比较多以外);
  • 纯香草味🌿 Javascript 写的,符合我的选型(我不会 TypeScript 和各种复杂的前端工具链);
  • 没有各种复杂的命令栏,我不需要,我都是手写;
  • 一句话完成原地替换 <textarea>

最最最重要的: 它不自带渲染功能!

很奇怪的需求?不奇怪!我的博客程序支持非常多的自定义渲染(基本上没有不兼容标准 Markdown),市面上的各种编辑器无一例外无法和我的博客兼容。而使用 TME 我就完全可以自己渲染。这样就可以把编辑器做得非常小而美。

所以最终选了它,没想到 bugs(主要是 Firefox 上)这么多呢?🥹

编辑器这种复杂的东西我不敢碰,所以都是提 issues,没有 pull-requests。

谁人一天大周末的不出去约妹子还在家写代码给人家提 issue 啊?是我🙃。

2条评论 页首

Go 的 switch-case 语句其实是允许重复值的

Go 语言至今都不允许当全局变量的初始值是函数返回值时,全局变量的类型被定义成带 const 修饰。比如下面这样的语句不被允许:

1
2
const n1 = math.Max(1, 2)
// math.Max(1, 2) (value of type float64) is not constant

真的很迷,可能 Go 语言认为 const 必须全宇宙级别的不变,不能是程序初始化来的。

这就导致类似 goldmark 里面像下面这种看起来像常量的全局变量,实际上,并不是:

1
2
3
4
package ast

// KindHeading is a NodeKind of the Heading node.
var KindHeading = NewNodeKind("Heading")

我一不小心写了个 switch-case 语句,包含了重复的 case 值,竟然不报错:

1
2
3
4
5
6
switch node.Kind() {
case ast.KindHeading:
	// ...
case ast.KindHeading:
	// ...
}

看着是有那么点儿怪怪的吧?还好我有习惯是会在提交代码前会再 review 一次,不是简单地 git add .。(不点名批评前上司)

而恰好这两个 case 的单测也不冲突(case 里面有条件判断),导致还真就没发现问题。

然后我就跑去看了看语言规范

Implementation restriction: A compiler may disallow multiple case expressions evaluating to the same constant. For instance, the current compilers disallow duplicate integer, floating point, or string constants in case expressions.

没毛病,make sense。只是……啥时候让已初始化的全局变量可以定义成 const?

没有评论 页首

2024-05-17.md

待办事项

  • 错误页面
没有评论 页首

和浏览器较量缓存的有效/刷新时机已经很久了,看起来目前取得了比较完美的表现。

目前对一篇文章返回了以下头部字段:

1
2
3
Last-Modified: Thu, 16 May 2024 00:10:09 GMT
Etag: HEAD-1715836710-1715818209-1715817446
Cache-Control: max-age=0, must-revalidate

从上往下:

  • Last-Modified 只表示文章本身最后的修改时间。

    早期的时候我只用有这个,但是明显不够用。比如博客的主题发生了变化时,页面也应该算更新。为了不改变这个字段本身的含义,我使用了 ETag 字段。

  • ETag 实体标签,另一种用来表示实体有没有修改过的方式,是对 Last-Modified 的补充。

    它就是个普通的字符串,内容可以自己写。我上面的格式是:${GitCommit}-${主题修改时间/系统启动时间}-${文章内容修改时间}-${评论更新时间}

    很复杂吧?其中任何一个的更新都会导致页面缓存失效。

  • Cache-Control 缓存控制。控制缓存保留的时长、刷新策略。

    max-age 表示缓存多久算新鲜,不新鲜就算过时了(过时不代表不可用)。 后面的 must-revalidate 表示对于过时的内容,必须重新检查是否还可用(也就是 304 状态码检测)。

    不知道我对于我设置的这个值是否完全理解,我的需求是:缓存你随便保存多久,但是总是帮我 revalidate 一下就行。如果不设置为 0,浏览器可能并不会 revalidate。但是设置为 0 我又不知道浏览器会不会不要缓存总是立即删除。

    但是目前看起来不会删除,如果 revalidate 后还有效,会继续用。

以上的缓存控制只是针对文章主 HTML 本身(即 Document)。资源文件(Js/Css)我加了一个较短的 max-age。如果换成给资源文件 URL 加上版本号的方式,理论上,可以把缓存有效期设置成永远。

本地开发的过程中,如果只是对主题本身进行了修改(而不是文章),比如样式和字体,此时需要刷新。如果没有 ETag,简单的做法是强制刷新,但是,强制刷新会使字体文件也没必要地全部重新加载、页面还会回到页首!这是非常不能忍的。不强制刷新的话,页面的滚动位置会保持一致。这对于观察样式的细微修改会很舒服的。

没有评论 页首

最近这火狐浏览器不知道是咋回事,打开一个新连接的速度无端慢到发指,我还找不到原因:

blocked

但是 Chrome 和 Safari 没有问题🙂‍↔️。

5条评论 页首

2024-05-15.md

待办事项

  • plantuml 测试页面
  • ssh-agent
没有评论 页首

Safari 果然是新时代的 IE,果然该死,Mac、iPad、iPhone 三个系统上的浏览器显示效果均不一样,放弃了😇,浪费生命。


测试用例:font-size.html
操作步骤:用手机 Safari 浏览器打开即可。如果发现左右的字体大小不一样,那么 bugs 复现了!

源代码(方便手机阅读,不出意外的话,字体显示大小也是错乱的):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>

<body>
<table>
<tbody>
<tr>
	<td>
		<pre><span>A</span>B</pre>
	</td>
	<td>
		<pre><span>A</span>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB</pre>
	</td>
</tr>
</tbody>
</table>
</body>
</html>

在[StackOverflow]上面问了也没人能回答:https://stackoverflow.com/q/78539386/3628322

把一个属性来回切换居然样式无法还原:

2025-6-9 16:41:34

这个问题应该已经修复了:fix ios code font size · movsb/taoblog@5ceae8a

参考:

没有评论 页首

最近几个月洗脑次数最多的歌:周慧敏 - 《最愛》

1条评论 页首