MoreRSS

site iconaquausora | 澄沨修改

生于上海,法学生,爱好二次元。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

aquausora | 澄沨的 RSS 预览

《向山进发》巡礼·富士山吉田线

2026-08-18 23:01:00

初次见面,富士山初めまして、富士山

自从在下来到日本之后,已经过去一年有余,这期间,自然少不了跑去各处游山玩水。尽管足迹多集中在关东和东海一带,但也收获了不少见闻,只是时常事务缠身,不太有精力将见闻整理成行纪,加之千叶—东京—神奈川—静冈一带的名胜,实在太过有名,不要说行纪文章,随便一个视频网站的旅游 Vlog 都多如牛毛。这些内容珠玉在前,使得在下的行纪即使写成,新奇之处也多半乏善可陈,至多只能当作流水账看看。

除了单纯的旅游之外,圣地巡礼也是诱使在下出门的一大因素。实际上圣巡给在下的动力可能要比单纯的观光更大一些,例如作为前拉拉人的在下,就去了不止一次距离东京三个半小时车程的沼津新干线还是太贵了,不舍得坐其实还是坐过一次。只是在下最初与好友定下去富士山的计划时,最开始倒完全没有圣巡的意思,只是单纯想去挑战一下日本最高峰。因为在下当时还没有看《向山进发やモノススメ》,只是从友人那里得知富士山也是其圣地而已,也因此没有特意做圣巡的准备,而第二次再去时,主要的目的则变为了圣巡。

说回正题,《向山进发》当中,主角团曾两度攀爬富士山,都是标准的两日登山方案,即第一天晚上留宿山小屋,第二天凌晨起床攻顶,到山顶观看日出御来光。分别是第二季的第 9-11 集和第四季的第 11-12 集。第一次攀爬,あおい日向ひなた以及心夏ここな四人攀登吉田路线吉田ルート。葵爬到八合目的太子馆太子館之后,出现高反症状,枫因此留下来照顾她,只有日向和心夏完成了登顶,四人同样从吉田路线下山。第二次攀爬,除了四人组之外,穗香ほのか也加入到登山的行列中。五人从须走路线須走ルート攀登,途中葵爬到本七合目的见晴馆見晴館之后,再次出现轻微症状,日向陪她就地留宿,其余三人前往八合目提前预定好的山小屋休息,最终五人皆成功登顶,自御殿场路线御殿場ルート下山。

这里补充一下背景知识,富士山共有四条登山路线,分别是吉田、须走、御殿场和富士宫路线。其中吉田路线是历史最悠久,也是登山客最多的路线;须走路线开始的地貌是森林,到本八合目之后与吉田路线合流;御殿场路线最长,大部分时间将行走在松软细碎的火山沙砾上;而富士宫路线富士宮ルート最短,攀登难度也相对最大。富士山每年 7 月上旬至 9 月 10 日开放登山路线及沿途设施,其中吉田路线 7 月 1 日起即开放,其余三条路线要等到 7 月 10 日,绕山顶一圈お鉢巡り的路线和除了扇屋扇屋之外的山顶设施也同样要等到 7 月 10 日才开放。

在下与好友于 2025 年 7 月 8 日第一次前往攀登富士山,由于是初见,因此选择了最传统的吉田路线,而这也恰巧与主角们的路线不谋而合。我们在 Busta 新宿バスタ新宿坐上直达富士苏巴鲁五合目富士スバルライン五合目(即吉田路线登山口)的大巴,两个小时左右就到达了目的地。由于苏巴鲁五合目的海拔已有 2305 米,因此一下车,我们就感受到了山风裹挟而来的阵阵凉意,比起上车时夏日炎炎的新宿,实在是爽快了不少。我们的运气不错,当日的天气非常好,登山指数全是 A 级,抬头望去,富士山山顶正被云层遮蔽,不见真容。

时已至中午,我们简单地拍完照,决定先吃点东西再攀登。友人提起在动画中,主角团品尝了这里的名物「喷火咖喱噴火カレー」,我们很快找到动画中的同款店铺「富士山见晴富士山みはらし」,各自点了一单。

总体的还原度还是不错的,只是感觉米饭和萝卜干还是动画中的更多一点。

吃完咖喱之后,我们又在友人的提醒下,和主角团一样各自买了一根「金刚杖金剛杖」,这是以前的登山客在登山时使用的一种木制八角形手杖,除了当作登山杖使用之外,还可以在沿途的各山小屋支付一定费用,在杖上盖上各山小屋专属的烧印作为登高纪念。

在下选的登山杖约有一米三左右的长度,虽说比起动画中心夏和葵她们买的短,但是考虑到之后可能有的带回国的问题,在下依旧觉得买长了。另外,在回家的电车上这玩意当然也只能拿在手上(笑)。因此,若是不在意还原度,在下更推荐购买五六十厘米的短棍。

必要的准备全部完成,我们一手拿着金刚杖,一手攥着提前准备好的登山杖,正式踏上了吉田路线的登山口。

吉田路线的开端是一段平缓上升的道路,与其说是爬升,倒不如说是绕山而行。这也是为什么明明是「吉田路线」,起点却不叫「吉田五合目」而是「苏巴鲁五合目」。因为真正的吉田路线实际上在这段路的尽头,到了那里,爬升的路段才算真正开始。

路上会路过一处山体加固设施,由于当时并没有拍巡礼图的意识,因此角度有偏差。

走了大约半个小时之后,眼前便出现了一处三叉口,这里便是六合目,也是真正的吉田路线的开始,路标指示,向上是富士山山顶,而向下则是真正的吉田五合目。同样地,由于此照片也没有对照动画来拍,因此视角完全反了。

从六合目开始,登山道变成了坡度约在 5-15 度之间的碎石子坡,呈「之」字绵延向上,这一段难度依然不大,但路程较长。从开始到下一个山小屋「花小屋花小屋」的所在地,也就是七合目,大约需要走一个小时。

花小屋的烧印样式与动画略有区别。

七合目往上,石子坡突然变成了一段一段的岩石地貌,传统的「道路」概念时常消失不见,需要靠设置在乱石间的铁链指路。爬升的难度稍增,有些地方需要手脚并用来攀爬,使用过长的登山杖会比较危险,需要格外小心。

同行的友人的攀登速度不及在下,因此在下主动帮他提了一个大食品袋,也因此占用了一只手。在攀登一处较高的台阶时,在下不慎踩到松动的岩石,靠单手没能稳住身形,身体的半边狠狠撞到了旁边的石壁,造成了一些擦伤,不过好在没有大碍,稍稍休息之后便能继续前进。

岩石路段一直延伸到八合目,虽然较长,但是途中山小屋密集,即便是体力不佳者,只要慢慢来,再加上在山小屋处多加休息,完全可以顺利攻克。

主角们正在烧印的地方是从七合目上来不久的日出馆日の出館,自日出馆再往上,不多久便能到达下图的巴馆トモエ館

值得一提的是吉田路线一共有两个巴馆,一个位于七合目,另一个位于本八合目,与须走路线合流处,这次在下与友人所宿之处便是后者。

从巴馆再经过一番约一个多小时的漫长攀登,途径镰岩馆鎌岩館富士一馆富士一館,举头便可望见一座红色的鸟居,那里正是鸟居庄鳥居荘的所在地,到达这里,也就意味着很快就能到八合目了。

此时,我们所处的位置已经相当高了。云层将我们笼住,脚下的火山砂岩被弥漫的水汽打湿,每走一步都如同在云中漫步,正是:天上有行云,人在行云里。

下为鸟居庄的烧印,烧印的大叔似乎不小心手抖了(笑)。

从鸟居庄继续攀登,经过东洋馆東洋館,越过八合目。熟悉的沙砾道路再现,只不过坡度要比六合目时更高一些,周围的植被也变得稀少,长时间的攀登与升高的海拔令友人渐渐出现呼吸不畅,休息时也时不时拿出在山下买的氧气罐吸上两口。

快要进入傍晚时分,我们也终于赶到动画中葵体力不支,和枫一起留宿的地方——太子馆。

太子馆往上,依旧是绵延不断的土坡,虽然脚下已经开始疲累,但若是能掌握好登山的节奏,调整呼吸,这段路还是不难的。

此时我们已身处云层之上,向东边望去,雾蒙蒙的,什么也看不清楚。太阳已经落到山的那一边,富士山的影子投射在大地上。登山道也阴了下来,迎面吹来的山风夹带起一丝寒意。

动画当中,心夏和日向在攀登这一段山路时已是黄昏。

过了蓬莱馆蓬莱館之后,便是白云庄白雲荘,过了白云庄,又有元祖室元祖室

天高地远,足履浮云,极目远眺,遗世独立。青冥浩荡不见底,日月照耀金银台。步云一曲语春莺,千山洗空烟雾横。

在经历了四个小时左右的攀登之后,我们来到了本八合目的富士山旅馆富士山ホテル,抬头望去,便能看到我们此行所预订的山小屋——巴馆了。

下午五时三十分许,我们完成当日的既定目标,到达海拔 3400 米的巴馆,并在此住宿。

不多时,太阳便行将落幕,天空中弥散出淡雅的霞光,月亮也趁机变得明亮。山下风起云涌,灰色的云海一路延伸到看不见的远方。

我们选择的住宿套餐包含了一顿晚饭,内容和动画一样,是喜闻乐见的咖喱和矿泉水,只不过量确实有点少,但看在能吃上一顿热食的份上,倒也还算可以接受。难道太子馆的晚餐还多给两根香肠吗,太子馆你这家伙

巴馆的住宿条件算是山小屋当中不错的,床位之间有木板隔开,每个隔间都有独立的充电插座,厕所和其他山小屋一样,在屋外的别间,当然,这里的住客使用是不收费的(使用富士山上的厕所基本都要收费)。

由于第二天凌晨需要起床登顶,因此我们吃完晚饭之后,便早早躺下。从这里攀登到山顶所需的时间大概是一个半小时,考虑到第二天的日出时间是 4 时 26 分,我们计划凌晨两点就起床准备。

在下在去西藏游玩的时候,就存在到了高海拔地区的第一晚难以入睡的问题,这次也不例外。不过虽说没有完全睡着,多少一直维持着半梦半醒的状态,倒也恢复了不少体力。


2025 年 7 月 9 日凌晨 2 时,巴馆的大厅灯火通明,榻榻米的长桌旁,登山客们或拿出随身携带的食物补充能量,或整理着自己的装备,为即将开始的攻顶做最后的准备。小屋外,山风清寒,陆陆续续有全副武装的登山客路过小屋门前,向着山顶进发。

在下吃过准备好的面包,穿上外套,带上头灯,便和友人一同换上登山鞋,加入到攻顶的行列之中。

屋外的天空一片漆黑,只有远处城市的灯火映出大地的轮廓。登山道上,无数盏头灯发出的光连成一条蜿蜒向上的线,直到远处看不到的山巅。

巴馆正好位于吉田路线和须走路线的合流处,隔壁就是须走路线的山小屋本八合目胸突江户屋本八合目胸突江戸屋。只不过当时须走路线尚未开放,没有登山客从那里合流过来,因此到山顶的这段路,总的来说不算拥堵。

从本八合目一直到九合目的路面,基本都是沙砾、大石块构成的,坡度很大,也很容易打滑。第一次走的时候,若是掌握不住方法,很容易走一步滑半步。我们小心地摸索着向上攀登,一路上只有风声和鞋底摩擦沙砾的声音,只有超过别的登山客,或是被人超越时,才偶尔能听到对方喘着粗气的声音。

行不多时,在下觉得有些冷了,便从包里拿出薄羽绒服穿上,夜间山顶的气温和冬天差不多,尤其需要做好保暖措施。只是可能因为在下攀爬的速度有点太快,喘起气来不说,还出了不少汗,等爬到九合目,汗水已经有点打湿衣服,冷风一吹,颇具寒意。

九合目以上,登山道变得更加陡峭,岩石路段也重新出现,很多时候需要高抬腿大跨步地向上挺进,随着离山顶越来越近,负责引导登山队伍的人员也开始出现,站在登山道上提醒大家控制好节奏,离山顶已经不远了。

在沿着丛生的泛红火山岩往上攀登了不知多少拐之后,我们终于来到了久须志神社久須志神社,此处已是海拔 3600 米,距离山顶只剩最后 300 米的路程。

远方的天空渐渐泛出鱼肚白,由头灯连成的光线清楚地指向山巅,我们一步一步向前迈进,踏着被我们的头灯照得雪亮的登山道。15 分钟之后,我们看到了山顶的鸟居与两侧的狛犬——穿过鸟居,那里就是山顶。

踏上最后几级石阶,映入眼帘的便是:富士山顶上浅间大社奥宫富士山頂上浅間大社奥宮的石碑,标志着我们通过吉田路线成功登顶。可惜此时山顶营业的只有扇屋,没法像动画那样在金刚杖的最上头敲上来自山顶的印记。

由于当时所持的手机夜间模式着实一般,这里的照片乃日出之后补拍的。

登顶的人已有不少,好在一来当时还不算登山季人最多的时期,二来我们登顶的时间也算比较早,我们很快就在扇屋前的一处空地找到了看日出的位置。

黎明前的黑暗已然过去,东面的天空开始泛蓝,残存的星星渐渐褪去,分隔大地与天空,划破昏蒙影的,是一线暗红色的霞光。

我们坐在空地上,西边刮来的风呼呼地往我们背上直吹,汗水由温热变得冰冷,在下裹上了带来的所有外衣,却依旧觉着有些发冷,忙吃了些食物,又从包里拿出防灾用防水材料裹上,这才感觉舒适了一些。

登顶的人越来越多,大家纷纷占好了位置,架起一排排镜头,对准东边,静静地等待。墨色的大地上,山峦的轮廓渐渐变得清晰,如同黑色的脊梁,将一方天地托举。片云由铅灰慢慢泛出幽暗的银白,随着天幕大亮,世间的万物都在等待,等待那一缕刺破黑暗的曙光。

伴随着山顶众人紧紧的注视,突然间,明与暗的交界,地平线的尽头,好似一颗滚烫的火星,又似一枚行将熄灭的炭火,暗色的束缚被烧开。人群爆发出一阵欢呼与赞叹,转眼间,火星变为饱满的赤弧,炭火不再苟延残喘,而是以不可阻挡的势头喷薄开来,将它触碰到的一切都染上灼烧的颜色。

大地的纠缠与夜色的合围轰然溃散,旷野之火在跃动,释放出无数的光和热,将光明与暖意撒向四方大地,浓烈的霞光将天空染红,扁平的黑色世界至此变得立体、厚重,拥有了生生不息的力量。

积蓄了整夜力量的金轮,此刻如同璀璨的明珠,变得难以用肉眼直视,万丈金芒普照大地,风中的寒意渐渐蒸发,被洗礼的大地睁开了眼睛,被晕染的天穹彻底换了颜色,古老的万年富岳,此时此刻,宣告彻底进入了白昼的统治。

见证了令人屏息的华丽日出之后,一旁西班牙面相的外国登山客操着不甚流畅的英语,请在下帮忙录制视频,在下本也想用英语回应,结果不知怎的「Yes」「Yes」到了嘴边却自动变成了「はい」「はい」,最后不得不日英混杂着帮忙拍完了视频。

日出后不久,山顶的温度就很舒适了,在下脱去了多余的外套和羽绒服,只穿着短袖衬衫随友人一同转山。正是这个举动致使在下被晒伤,因此在山顶一定要做好防晒

尽管官方明面上因为其他三条登山路线还没有开放,转山的线路同样处于不开放的状态(要等到 7 月 10 日),但实际上依旧可以转山。我和友人的体力尚可,遂踏上了转山的路途。

在途中远眺富士五湖之一的山中湖,在下觉得这张照片的云其实更好看(笑)。

顺带一提,在下在十个月之后也造访了山中湖—河口湖,拍了很多经典的富士山以及摇曳露营ゆるキャン△的部分巡礼图,但是图大多比较散,若有好的灵感,或者是有机会去一趟本栖湖露营+圣巡的话,将来考虑整理成文章发出来。又开始挖坑

我们向着最高峰剑峰方向,沿着顺时针转山,约一刻钟之后,便到达顶上富士馆頂上富士館。这里也有一个顶上浅间大社奥宫,旁边是日本最高的邮局——富士山邮局。不过因为转山路线没有开放,这些设施也同样要等到第二天才开始营业。

走过顶上富士馆,立马就能看到富士山最高峰——海拔 3776 米的剑峰。

前往剑峰的这一段土坡,坡度有将近 40 度,爬起来非常容易打滑,甚至呈五体投地的姿势摔倒,若是实在把握不好平衡,可以抓着最左边的栏杆攀爬。

爬上这段土坡后,便是富士山真正的顶峰,这里坐落着一座气象观测站,观测站前,便是「日本最高峰富士山剑峰日本最高峰富士山剣ヶ峰」的石碑。从这里向下看去,还能看见富士山的火山口里,尚有未融化的坚冰。

拜托其他登山客在碑前留完影,我们继续前进。当日的云不多,山峰西面,北面的风景一望无际,极尽辽阔。真可谓「会当凌绝顶,一览众山小」,而富士山作为高达 3700 米的孤峰,在其绝顶之上感受到的众山之小,感觉恐怕是泰山也难以比及的。

如果在这里失足的话,人生就完蛋了吧(笑)

过了一会,我们便绕回了登山道的终点。掐指一算,绕山顶一圈大约用了一个小时左右。此时的我们不免觉得有点疲乏,也希望尽早坐上回东京的巴士,另外,在转山的途中友人想起有东西似乎落在山小屋,遂决定就此下山。

下山道的开始一段是和登山道共用的,也因此在下有幸拍得久须志神社和山顶鸟居在白天的样子。

下山道到八合五勺左右和登山道分流,不过我们为了取回遗落的物品,一直沿着登山道下到了本八合目,随后才正式踏上吉田路线的下山道。

吉田路线的下山道比起登山道来可谓乏善可陈,因为其本身就是由推土机开辟的路线,除了火山沙砾和无尽的「之」字之外几乎一无所有。唯一值得一提的就是下山的途中起了大雾(实际上是云层变厚了),使得普通的下山道多了几分神秘色彩。

正如动画中葵所言,在下在下山途中也萌生出「要走多远啊」的悲叹。持续的下坡已经令膝盖不堪重负,而细碎的砂石不仅令道路变的更滑,还无孔不入地往鞋子里钻,几乎每走完一段短坡,就会有许多石子灌进在下的登山鞋中,使得在下不得不每隔一两个「之」字便停下来,把鞋子里的石子清理干净再上路。

于是就这样一路走走停停,我们花了将近三个半小时才终于回到富士苏巴鲁五合目,途中,在下甚至对穿戴着防沙袜套的登山客生出羡慕之情——如果有同样想挑战富士山的阁下,请务必要给自己准备好防沙袜套啊!

在经历了地狱般的下山道的摧残之后,拖着僵硬的腿、不愿打弯的膝盖、燃尽了的股四头肌,在下甚至觉得走回苏巴鲁五合目的平路都显得又臭又长。古语云:「上山容易下山难」,果如是也。

回到最开始出发的地方,这里俨然成为了雾中仙境,也使得友人直至今日都对富士山的雾念念不忘,为此说过:「会为了富士山的雾再登一次富士山。」而在下只想着和动画中的葵一样就地躺下,好在很快巴士就来了,有的是时间在回东京的巴士上好好睡上一觉。

こんにちは、Astro

2026-07-25 11:55:00

NOTE

封面来源:newskin | 养病中低浮上

迁移背景#

自把敝站从 WordPress 迁到 Hexo,已三年有余。彼时 Astro 才刚刚发布第一个 Beta 版本不久,尚不为在下所知。直到 2023 年底,在下才终于了解到这个推行「群岛架构」的框架,不过当时的 Astro 社区生态还处于起步阶段,对于低技术力的在下来说,将其作为博客框架来用还为时尚早。况且,Volantis 主题的优化做得还不错,在下也没有在博客里塞进大量的 JavaScript 资源,因而 Lighthouse 评分还是看得过去的。另外,敝站的部署早就扔到了 Serverless 服务上运行,对部署时间的长短并不敏感,对服务器渲染更是没有要求,因此,没有必要追求那一点点性能提升而放弃现有成熟的解决方案。

虽然如此,在下依旧对 Astro 的 View Transitions API 印象深刻,无论是切换页面时的体验还是平滑的原生动画,都是老旧的 Hexo 打补丁所不能及的。因此,在下还是在心中暗自决定了下一代的敝站将会由 Astro 驱动,并为此持续关注着社区当中的新主题。

在下最早关注的主题是 fuwari,基于 MD3 风格的设计一下子抓住了在下的眼睛。不过 fuwari 依旧缺乏一些基本的博客功能,例如文章目录(现在已经支持)、评论模块和友链页面,虽然可以自己手搓,不过对于在下来说还是有些费时费力,仅仅只是将其拉到了本地略微研究了一番,便就此作罢。

随着时间的推移,更多有趣的主题开始涌现,其中基于 Hexo 主题 Shoka 设计的 koharu 吸引了在下的注意。Hexo 的 Shoka 本就是在下比较喜欢的主题,但在下同时也注意到更多基于 fuwari 修改的主题开始出现,例如 TwilightMizuki 等,都是在下比较中意的。最终,在下在左挑右拣中选定了 MD3 设计的 Mizuki。

迁移备忘#

比起上次从 WordPress 迁移出来,这次的迁移就要方便的多了。首先,由于文章都是以 MD 文档的形式储存,只需要简单地复制粘贴,改一下 Frontmatter,就可以直接用了,唯一需要注意的是 Volantis 主题的特色功能代码需要适配新主题,不过这充其量只是字符串替换,无论是手动 Ctrl + F 之后批量替换还是直接让 AI 修改都不算费事。

而在上次迁移花费最多精力的评论方面,由于之前使用的是 twikoo 评论系统,只需要引入前端 JS 并连接到之前的数据库,就可以像模块一样方便地在不同的博客之中插拔。

值得一提的是,Mizuki 给 twikoo 写的样式还是基于 1.7.6 的,而在在下部署博客的时候,发现其对当时 twikoo 最新的 1.7.13 的适配有问题,为此拷打了一番 AI,提交了 PR 把这个问题给解决了。

最终,在迁移过程中最花时间的项目落到了对主题的微调上,由于这是在下首次接触到 Astro 项目,花了一点时间才搞明白文件结构,特此把一些重要的修改项目列出来备忘。

字体#

IMPORTANT

Mizuki 在 2026 年 8 月 6 日的提交中,对字体的引入格式再度作出更改,请以最新配置为准。

Mizuki 之前的字体配置在 src/config/siteConfig.ts 中调整,不过后来由于一些问题,转而直接使用 Astro 原生的字体 API 配置,需要到 astro.config.mjs 中修改。

Astro 的字体 API 可以非常方便地引用敝站使用的谷歌字体:

2026-08-06 后

astro.config.mjs
export default defineConfig({
fonts: customFontsEnabled
? [
{
name: "JetBrains Mono",
cssVariable: "--font-jetbrains-mono",
provider: fontProviders.fontsource(),
styles: ["normal", "italic"],
},
{
name: "Noto Sans",
provider: fontProviders.google(),
cssVariable: "--font-body",
weights: [400, 600],
// These variables are composed into --font-sans below. Keep their
// fallback lists empty; otherwise a system fallback after this Latin
// font prevents the following CJK font from ever being considered.
fallbacks: [],
optimizedFallbacks: false,
},
{
name: "Noto Sans SC",
provider: fontProviders.google(),
cssVariable: "--font-cjk",
weights: [400, 600],
// The final system fallback belongs to --font-sans, not this partial
// CJK font stack.
fallbacks: [],
optimizedFallbacks: false,
},
{
name: "Lobster",
provider: fontProviders.google(),
cssVariable: "--font-lobster",
},
{
name: "Rampart One",
provider: fontProviders.google(),、
cssVariable: "--font-rampart-one",
},
]
: [],
});

2026-08-06 前

astro.config.mjs
export default defineConfig({
fonts: [
{
provider: fontProviders.google(),
name: "Noto Sans",
cssVariable: "--font-body",
weights: [400, 600],
},
{
provider: fontProviders.google(),
name: "Noto Sans SC",
cssVariable: "--font-cjk",
weights: [400, 600],
},
{
provider: fontProviders.google(),
name: "Lobster",
cssVariable: "--font-lobster",
},
]
});

需要注意的是 Mizuki 必须要有 --font-body--font-cjk 这两个 CSS 变量,修改的时候要确保这两个变量被正确配置,不然会报错。

astro.config.mjs 中引入之后,就可以在 src/styles/main.css 中进一步自定义了,例如敝站:

2026-08-06 后

src/styles/main.css
@theme {
--font-sans: var(--font-body, ui-sans-serif), var(--font-cjk, system-ui), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-display: var(--font-lobster), var(--font-body, ui-sans-serif), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-title: var(--font-rampart-one), var(--font-body, ui-sans-serif), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}

2026-08-06 前

src/styles/main.css
@theme {
--font-sans: var(--font-body), var(--font-cjk), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-display: var(--font-lobster), var(--font-body), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-title: var(--font-rampart-one), var(--font-body), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}

如果在 astro.config.mjs 定义了新的字体变量,不要忘记在 src/layouts/Layout.astro 中引入,否则不会有效果,例如敝站在这里新引入了 --font-lobster

2026-08-06 后

src/layouts/Layout.astro
<head>
<meta charset="UTF-8" />
<style is:inline>
@layer properties, theme, base, components, utilities;
</style>
{customFontsEnabled && <Font cssVariable="--font-body" preload />}
{customFontsEnabled && <Font cssVariable="--font-cjk" />}
{customFontsEnabled && <Font cssVariable="--font-jetbrains-mono" />}
{customFontsEnabled && <Font cssVariable="--font-lobster" />}
{customFontsEnabled && <Font cssVariable="--font-rampart-one" />}

2026-08-06 前

src/layouts/Layout.astro
<head>
<meta charset="UTF-8" />
<Font cssVariable="--font-body" preload />
<Font cssVariable="--font-cjk" /> // [!code highlight]
<Font cssVariable="--font-jetbrains-mono" />
<Font cssVariable="--font-lobster" />
<Font cssVariable="--font-rampart-one" /> // [!code ++]

顶栏菜单#

Mizuki 使用 Tailwind CSS,只需找到位置,调整起来还是很方便的。

  • 调小元素之间的间距:在 src/components/organisms/navigation/DropdownMenu.astro 的第 44 行及 106 行处分别调小 lg:px-5 的值
  • 防止左侧 LOGO 被挤压后整体下移:在 src/components/organisms/navigation/Navbar.astro 的第 103 行处删除 shrink-0
  • 二级菜单取消右侧保留空白:在 src/components/organisms/navigation/DropdownMenu.astro 的第 153 行处把 min-w-[12rem] 改为 min-w-max

永久链接#

Mizuki 的文章链接默认存在 src/contest/posts 下,使用默认的文件名作链接,默认链接路径为 /posts/文件名/,如果不想要前面的 /posts/,则需要开启 src/config/permalinkConfig.ts 中的 PermalinkConfig 功能。不过,即便开启永久链接之后,旧有的带 /posts/ 的链接依旧能访问到文章。

这里有一些值得注意的问题,一是使用永久链接访问的文章,底部的「上一篇文章」「下一篇文章」按钮依旧会导航到带 /posts/ 的链接;二是最底部的主题相关文章和随机文章模块不显示。排查后发现,主要原因出在组件内部的硬编码以及永久链接的路由组件缺失。

要解决上述问题,首先就要让模块和按钮在生成数据时,就携带计算好的文章路径。来到 src/utils/content-utils.ts,将第 45 行 getSortedPosts 处改为:

src/utils/content-utils.ts
export async function getSortedPosts() {
const sorted = await getRawSortedPosts();
for (let i = 1; i < sorted.length; i++) {
sorted[i].data.nextSlug = sorted[i - 1].id;
sorted[i].data.nextSlug = getPostUrl(sorted[i - 1]);
sorted[i].data.nextTitle = sorted[i - 1].data.title;
}
for (let i = 0; i < sorted.length - 1; i++) {
sorted[i].data.prevSlug = sorted[i + 1].id;
sorted[i].data.prevSlug = getPostUrl(sorted[i + 1]);
sorted[i].data.prevTitle = sorted[i + 1].data.title;
}
return sorted;
}

再将第 382 行处开始的两个循环改为:

src/utils/content-utils.ts
for (const s of withTagMatch) {
if (result.length >= maxCount) break;
result.push({ id: s.post.id, data: s.post.data });
result.push({
id: s.post.id,
data: s.post.data,
url: getPostUrl(s.post)
});
}
for (const s of withoutTagMatch) {
if (result.length >= maxCount) break;
result.push({ id: s.post.id, data: s.post.data });
result.push({
id: s.post.id,
data: s.post.data,
url: getPostUrl(s.post)
});
}

搞定了数据部分,再修改组件逻辑,使其能够读取传入的永久链接。先是上下文按钮的,来到 src/components/PostNavigation.astro 第 33 行处,将 <a> 标签作如下修改,这个链接对应「上一篇文章」:

src/components/PostNavigation.astro
<a
href={getPostUrlBySlug(prevSlug)}
href={prevSlug.startsWith('/') || prevSlug.startsWith('http') ? prevSlug : getPostUrlBySlug(prevSlug)}
class="w-full font-bold overflow-hidden active:scale-95"
>

第 52 行处的 <a> 标签也是同理,这个链接对应「下一篇文章」:

src/components/PostNavigation.astro
<a
href={getPostUrlBySlug(nextSlug)}
href={nextSlug.startsWith('/') || nextSlug.startsWith('http') ? nextSlug : getPostUrlBySlug(nextSlug)}
class="w-full font-bold overflow-hidden active:scale-95"
>

这样按钮就改好了,接下来修改相关文章和随机文章模块中携带的路径,来到 src/components/widget/PostListItem.astro 的第 34 行处,将 <a> 标签作如下修改:

src/components/widget/PostListItem.astro
<a
href={getPostUrlBySlug(post.id)}
href={post.url || getPostUrl(post as any)}
class="group flex items-center gap-3 px-3 py-3 -mx-1 rounded-lg transition-all hover:bg-black/5 dark:hover:bg-white/5 active:scale-[0.98]"
>

最后,补全永久链接的页面路由中的相关文章和随机文章模块,来到 src/pages/[…permalink].astro,找到:

src/pages/[...permalink].astro
import {
LastModified,
PostMeta,
PostNavigation,
} from "@components/features/posts";

部分,在 PostNavigation, 后面补上 RandomPosts,RelatedPosts,,接着找到:

src/pages/[...permalink].astro
import { getSortedPosts } from "@utils/content-utils";

getSortedPosts 这个变量加到 getSortedPosts 后面,再找到 import { licenseConfig } from "src/config";,将其改为:

src/pages/[...permalink].astro
import {
licenseConfig,
randomPostsConfig,
relatedPostsConfig,
} from "src/config";

随后在 Frontmatter 结束前(--- 前)补充:

src/pages/[...permalink].astro
const relatedPosts = relatedPostsConfig.enable
? await getRelatedPosts(entry, relatedPostsConfig.maxCount)
: [];

最后,在最后(</MainGridLayout> 前)补上:

src/pages/[...permalink].astro
{
(relatedPostsConfig.enable || randomPostsConfig.enable) && (
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
{relatedPostsConfig.enable && relatedPosts.length > 0 && (
<RelatedPosts relatedPosts={relatedPosts} />
)}
{randomPostsConfig.enable && (
<RandomPosts
excludeIds={[entry.id]}
maxCount={randomPostsConfig.maxCount}
/>
)}
</div>
)
}

到这里,问题就算全部解决。不过,在下建议顺便给带 /posts/ 的链接加个重定向,来到 src/pages/posts/[…slug].astro,在第 22 行引入 getPostUrl

src/pages/posts/[...slug].astro
import { getFileDirFromPath, removeFileExtension, getPostUrl } from "@utils/url-utils";

再于第 97 行 const { entry } = Astro.props; 后加入判断就好了:

src/pages/posts/[...slug].astro
if (permalinkConfig.enable) {
const targetUrl = entry.url || getPostUrl(entry);
if (targetUrl && !targetUrl.startsWith("/posts/")) {
return Astro.redirect(targetUrl, 301);
}
}

另外,出于对 SEO 的考虑,也一并建议修改 src/pages/robots.txt.ts,因为 Mizuki 的默认配置只允许首页和 /posts/ 下的地址被爬取:

src/pages/robots.txt.ts
import type { APIRoute } from "astro";
const robotsTxt = `
User-agent: *
Disallow:
Sitemap: ${new URL("sitemap-index.xml", import.meta.env.SITE).href}
`.trim();
/* 至少也要保证站点地图能被正常爬取
Disallow: /
Allow: /$
Allow: /posts/
Allow: /sitemap-index.xml
Allow: /sitemap-0.xml
Allow: /sitemap-1.xml(如果有)*/
export const GET: APIRoute = () => {
return new Response(robotsTxt, {
headers: {
"Content-Type": "text/plain; charset=utf-8",
},
});
};

更新 Twikoo 前端#

Mizuki 自带的源在 /assets/js/twikoo.all.min.js,可以选择下载最新版本将其替换,后端不使用腾讯云云函数的只需要 twikoo.min.js 即可。

也可以直接引用官方 CDN:https://unpkg.com/twikoo/dist/twikoo.min.js,需要在 src/components/comment/Twikoo.astro 中替换 TWIKOO_SCRIPT_URL

鼠标指针#

也算是敝站为数不多的自 WordPress 时代以来一直传承下来的特性。直接在 src/layouts/Layout.astro 添加:

src/layouts/Layout.astro
<style>
/* 1. 默认状态 */
html, body {
cursor: url('https://PATH_TO_YOUR_DOMAIN/normal.cur'), auto;
}
/* 2. 悬停与点击状态 */
a, button, [role="button"], summary, select, option {
cursor: url('https://PATH_TO_YOUR_DOMAIN/selecting.cur'), pointer;
}
a:active, button:active {
cursor: url('https://PATH_TO_YOUR_DOMAIN/selected.cur'), pointer;
}
/* 3. 文本输入与选择状态 */
input[type="text"], input[type="search"], textarea, [contenteditable="true"] {
cursor: url('https://PATH_TO_YOUR_DOMAIN/text.cur') 16 16, text;
}
/* 4. 等待/后台加载状态 */
.is-loading, .loading-state {
cursor: url('https://PATH_TO_YOUR_DOMAIN/waiting.cur'), wait;
}
</style>

适配动态页#

敝站的动态页基于 Mastodon embed timeline widget 制作,用于展示自己在 Mastondon 发表的内容,本质上是直接引用 JS。不过需要注意的是,Astro 需要把 JS 内容单独拿出来,用 script is:inline 放到 UI 孤岛中,否则将不会被加载。

另外,似乎必须完全刷新一次页面才能正确加载出页面内容,因此加入了强制刷新代码:

<script>
initMastodon();
document.addEventListener('astro:page-load', initMastodon);
</script>

最后是对主题颜色的适配:

<style is:global>
.mt-container,.mt-container[data-theme],.mt-dialog,.mt-dialog[data-theme] {
--mt-txt-max-lines: none;
--mt-preview-max-lines: none;
--mt-color-bg: rgba(255, 255, 255, 0);
--mt-color-bg-hover: rgba(233, 238, 241, 0);
--mt-color-line-gray: var(--line-color);
--mt-color-contrast-gray: var(--content-meta);
--mt-color-content-txt: var(--color-neutral-700);
--mt-color-hashtag: var(--primary);
--mt-color-link: var(--btn-content);
--mt-color-error-txt: var(--admonitions-color-caution);
--mt-color-btn-bg: var(--btn-regular-bg);
--mt-color-btn-bg-hover: var(--btn-regular-hover);
--mt-color-btn-txt: var(--btn-content);
--mt-color-backdrop: #00000090;
--mt-color-placeholder: #60698425
}
.dark .mt-container,.dark .mt-container[data-theme],.dark .mt-dialog,.dark .mt-dialog[data-theme] {
--mt-color-bg: rgba(255, 255, 255, 0);
--mt-color-bg-hover: rgba(233, 238, 241, 0);
--mt-color-content-txt: var(--color-neutral-300);
--mt-color-backdrop: #00000090;
--mt-color-placeholder: #60698425
}
</style>

迁移小结#

这次的迁移,在下大约花了一个周末的时间完成。除了上述必要的一些适配之外,在下还删掉了一部分文章封面,虽然封面确实能提高页面美观程度,但是给每一篇文章都加上封面反而让网站显得过于花哨,删掉一部分与文章相关不大的封面之后,看起来有了呼吸的空间,错落交致之间反而提升了整体的美观度;另一方面,也能变相加快网页的加载速度。

对于既往文章的修订当然也是必不可少的,不过对于这些琐碎的部分,就不再一一赘述。此外,由于架构迁移,旧有的一些功能,例如剧集页无法继续提供,不过有动态页的 NeoDB 消息补足,可以等之后再慢慢打磨上线。

在迁移的过程中,在下总是能迸发出最初搭建博客时的,发自内心的快乐,在电脑前一坐就是好几个小时,心无旁骛,无视外界的打扰,把食欲和困意也暂时放在一边,脑子里只考虑自己想要考虑的东西,进入全神贯注的心流状态。哪怕是结束之后只想瘫在床上被睡意裹挟,那种带给在下的充实感与满足感,也依然会从骨子里蔓延开来,告诉在下:博客在迁移,时代在变,但那份对折腾发自内心的热爱与专注,从未改变。

迁移后记#

针对后续的微调以及对 Mizuki 更新的一些适配,在此加笔记录。

使用 CDN 加载 Twikoo#

一直以来,在下习惯通过 unpkg 的 CDN 链接引入 Twikoo 前端,其能够自动选择最新版本的 JS 文件,省去手动更新的麻烦:

src/components/comment/Twikoo.astro
<script is:inline define:vars={{ config }}>
(function () {
const TWIKOO_CONTAINER_ID = "twikoo-container";
const TWIKOO_SCRIPT_URL = "/assets/js/twikoo.all.min.js";
const TWIKOO_SCRIPT_URL = "https://unpkg.com/twikoo/dist/twikoo.min.js";
const ROOT_MARGIN = "200px";

不在腾讯云云函数部署 Twikoo 后端的话,则不需要引入 twikoo.all.min.js

另外,不要忘记明文导入一下 twikoo.css 以防止可能的加载顺序问题导致样式不能正确覆盖:

src/components/comment/Twikoo.astro
---
import { commentConfig } from "@/config";
import "@/styles/twikoo.css";

暗色模式跟随系统设置#

Mizuki 默认不探查用户的系统深浅色设置,而是把没手动设置 theme 的用户直接设置为浅色模式。如果想要同步系统设置,可以在 /src/layouts/partials/HeadTags.astro,第 119 行之后,// Load the theme from local storage 之前加上:

/src/layouts/partials/HeadTags.astro
const systemIsDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
const currentSystemTheme = systemIsDark ? DARK_MODE : LIGHT_MODE;
localStorage.setItem("theme", currentSystemTheme);

岁暮杂记

2025-12-31 22:59:59

NOTE

封面来源:えびっ | ヘナチョコ

杪岁垂垂尽,寒花悄悄繁。又是一年,随着年岁的增长,每逢岁暮,似乎心中也总不由得隐隐生出悲秋之感。写博客快要 6 年了,阅遍所有文章,年终总结仅有前年的一篇而已。老实说,那篇总结多少是在下的跟风产物——在玩了近 4 年博客之后,在下才终于意识到有那么一个话题可以被拿出来在一年的最后水一篇文章——那两年也算得上是博客更新的高频期,几乎有什么想法,都会被在下迫不及待地转化出来,为此一连码上四五个小时的字也是常有的事。然而正如两年前的总结所说,毕业之后,闲云野鹤的生活渐渐远去,各类事务催着在下向前迈步。当习惯的生活节奏被打破,总有一些东西要面临取舍,而博客便成为取舍的牺牲品,更新的日期被一再拖延,有趣的想法即便被及时记录,新建了文件夹,甚至已经写了一部分,但随着各类因素的影响,也无法逃脱被搁置的命运。于是此时,本来只为跟风而作的年终总结,也是时候发挥它应有的作用了。

减肥#

从模糊的记忆、老照片与父母的口中,在下可以轻松得知,自己在小学三年级之前是偏瘦小的类型。不过,由于在二年级暑假摄入了过多的奶奶的蛋炒饭,因此在下不慎成为了超重儿童。亲戚朋友、左邻右舍见了,一个劲地夸赞在下变「壮」了。于是,这之后的很多年里,在下几乎没有动过减重的念头,一直把超重的体格维持了下去。随后,经历了高中三年的艰苦修炼,在下终究是越过了 BMI 28 的界限,成功晋升为肥胖人群。

闲云野鹤的大学生活是肥膘的绝佳培养皿,随着体测的成绩一次次下降,到了毕业时,在下的 BMI 已上升至 31.5。养膘容易减脂难,尽管知道自己应该做出改变,但是每日坐在电脑前成为了一种习惯,挪动沉重的身体早已变得困难。加上比起在学校时更加唾手可得的外卖,又过了 4 个月的时间,在下的 BMI 飙升至 33.3。

小时候亲戚评价在下「壮」并非没有道理,在下的身体属于比较会藏肉的类型,大量的脂肪堆积在了臀部和大腿,而肚子和下巴则相比没有那么突出。然而到了这个地步,即使再能藏肉也无济于事。无法忍受镜中自己的面庞,在下于 2024 年 11 月 6 日开始减肥。

虽然在下之前从来没有减过肥,但是还是了解过不少减肥理论,深知减肥的本质就是制造热量缺口。在下开始计算每天热入的总热量,将其控制在 1800~2200 大卡上下。不过,单纯的节食肯定是不可取的,因为那无法持续。为了抑制饥饿感,调节身体激素水平,提升减肥速率,运动是必不可少的。由于在下不喜欢跑步,住宅不是公房爬不了楼梯(下楼梯对膝盖的损伤大,因此一般选择坐电梯下楼),更不想去健身房,于是就决定在家对着 B 站视频跟练 HIIT——在下自认不算毫无运动基础。不过现在看来,也许做 2 区有氧会更加合理一些——第一天跟练 12 分钟的 HIIT,仅仅只做完 1 组(4分钟),在下的动作就完全变形了,但还是强撑着完成了。做完的那一刻,在下一屁股坐倒在瑜伽垫上,心跳简直像是蹦到了嗓子眼,过了整整 10 分钟都没能平静下来,还伴有强烈的恶心感,差点以为自己真的要交代了。

好在从第二天开始,就再也没有了第一天那样的恐怖回忆。在下每周 6 练,时间都控制在午饭前,周日则安排休息日+欺骗餐。体重便开始以一周一公斤的速度往下掉,虽然这个数字略有些快,但总体还能接受。过了一段时间之后,在下开始在晚上做一些哑铃运动,防止肌肉流失过快。得益于 HIIT 的锻炼,在下的心肺功能显著上升了,12 月份和朋友去爬黄山时,朋友已难以跟上在下的节奏。

体重秤上数字的不断下降激励着在下坚持下去。到了春节前后,在下已经累计减重近 20 斤,12 分钟的 HIIT 已经变得轻松,于是在下又在这之后加入了 15 分钟的 TABATA。就这样,到了 3 月末,在下那么多年来,第一次在体重秤上看到了 7 开头的数字。

4 月开始,在下的生活发生了巨大的改变:在下去了日本,居住在东京的寮里。虽然是一个人一间房,但是像以往一样继续做带有跑跳动作的 HIIT,显然对四邻相当不友好,因此在下便开始改做 40 分钟的无跑跳 HIIT。没有时间时,在下也会选择做之前一直以来做的 15 分钟的 TABATA,因为那套动作没有大跳,相对而言噪音在可接受范围内。

随着体重变小,减重的速度也慢了下来,从一开始的一周一公斤,变成一周一斤,又变成两周一斤……但是由于始终坚持热量控制和运动,体重下降的趋势也一直没有停下。8 月份趁着暑假回国时,在下的体重来到了 68 公斤以下,不过由于在下抱着放纵的进食态度加上国内低廉的外卖价格,暑假期间在下胖了 3 斤左右。好在这没有超出在下的预期,回到日本之后花了一个月时间把这 3 斤减掉了。

在那之后,在下开始感受到平台期的存在,体重在 67 公斤上下摇摆不定,腰围也不再大幅下降,大部分的肥肉已经被消耗完毕,剩下的脂肪都是些皮下的顽固脂肪。在下在换跟练视频的同时,也不再纠结减重速度,进而开始注重饮食结构。通过对 AI 的一番拷打,在下决定进一步减少零食的摄入,并开始购买蛋白粉,加入力量训练,每日维持 300 大卡的热量缺口,慢慢地消磨这些脂肪。

时至今日,在下已经减轻了 30 公斤的体重,完成了年初制定的减重至 65 公斤的目标,目前的 BMI 是 22.8,而最终目标是减重到 63 公斤,并维持在这个水平,再把重心慢慢转向增肌。最后的最后,在下希望自己能维持住的不只是体重的数字,还有这一年多以来一直坚持的饮食习惯与健身习惯。

赴日#

开始学新标日的两年后,小李赴日终究变成了在下赴日。

目标是考日本的大学院,当然,厉害的人会在国内学好然后直接旅游签飞过去考试。在下没有这个本事,由于在国内自学日语总是三天打鱼两天晒网,到赴日的时候对自身的日语水平依旧不自信,只能先从语校开始了。好在日常交流和上课是没什么问题的,只是考文科专业,N1 是敲门砖,所以 N1 的大山必须翻过去。

1 月开始,在下就开始用 Anki 背单词了,用的单词书范围涵盖了从 N1~N5,大概 2 万个单词左右吧,一开始每天背 40 个,到 4 月落地日本时,把 N3~N5 的单词基本都过了一遍。4 月落地之后开始猛冲 N1、N2 的单词,当时的背诵量大约是每天 80 个,复习量在 400 个上下。由于语法也有很多没学的,还要另外买教材多过几遍 N1 和 N2 的语法……现在回想起来,从 4 月到 7 月初考试的这段时间,确实是这一年当中最刻苦的时光了。

尽管每天背 80 个,也架不住单词多,到了考试当天,也不过把必考的单词背完而已,核心词的进度则不足三分之一 。但是苍天有眼,在下还是顺利通过了 N1,虽然分说不上有多高,但从分数上来看也不算很惊险,也许是汤岛天满宫的学问之神确实比较灵。

考过 N1 之后,又回国玩了半个月,感觉自己的状态就不如备战 N1 的时期了。尽管考学远比 JLPT 更重要,但是不知为何总感觉缺乏了一些干劲。每天背完单词之后(当然,考完之后也没有每天 80 个了),动力就大幅下降了,如今冬季考临头,自己却又陷入了没底的状态……感觉自己的弱点就是「尻が重い」,不到「尻に火がつく」的状态就不愿意好好努力。

在那之后唯一值得称道的,就是在下依旧坚持每天背单词,再过一周的时间,这本单词书就要被全部背完了。

旅行#

赴日之前,在下和朋友去了黄山与西安,还首次体验了滑雪。可惜的是这些游记至今仍未写成,本来订下每月更新一篇博客的计划,也自然而然落空了。

赴日之后能写的也有很多,作为一名动画爱好者,去了很多地方圣巡,都内就有很多圣地,刚来的那一周,几乎每天都是一两万步,跟着巡礼地图到处走。印象深刻的是由于那时樱花季还没结束,赶着那段时间跑去了练马巡礼四谎。

日本的黄金周期间,天气渐渐变热,跑去了镰仓和箱根。镰仓风光很好,游客很多,圣地也很多,灌篮高手是自然的,还有青猪系列、孤独摇滚等等,甚至是迪迦奥特曼都在这里拍过一集,可惜的是气温高,往富士山的方向望去,只能看到一团云雾,直到了傍晚才能望见一个影子。至于箱根,作为温泉胜地理应是去泡温泉的,只不过这次是陪 EVA 狂热厨朋友一起去,主要的任务变成了巡礼 EVA。

7 月的时候和另一个朋友一起去爬了富士山,为了看日出,晚上宿在八合目的山小屋,凌晨两点起来攻顶。尽管是 7 月,山顶的寒风却依旧凛冽,套着专门准备好的薄羽绒服也依旧冷的哆嗦,不过在太阳升起的那一刻,这一切都变得值得了。

7 月末作为水水人,去了水水人的快乐老家沼津。正值当地的花火大会,定不到合适的房间,只能住在邻近的富士。头一天与一位小红书上找的千歌厨作伴,后一天则自己单独游玩。这两天是在下今年活动量最大的两天,光是第二天就生生走了 4 万步。当然,也很满足。

之后就没有怎么到处跑了,基本都在都内活动,最近一次是和朋友去了立川简单地巡礼了一下魔禁 & 超炮。

大饼#

因为各种各样的原因,在下搁置了相当一部分的文章写作计划,尽管其中有些已经颇有时日了,但是在下依然希望能尽量抽时间把它们全部完成。

  • 2024 年 12 月游黄山的游记
  • 2025 年 2 月游西安的游记
  • 2025 年 4 月以来部分圣地巡礼的记录
  • 2025 年 7 月登顶富士山的游记
  • 作为淡坑的拉拉人,借 2024 年 10 月 6 日参加的 LoveLive! Series Asia Tour 2024 ~みんなで叶える物語~和 2025 年 6 月 21 日参加的 Aqours Finale LoveLive! ~永久 stage~这两场 LIVE 作 2016 年入坑 LL 以来的总结与感想
  • Comike 初参战——C106 参战记录
  • 折腾 n8n 的相关笔记

今年定下的观影量达标,读书量仍有待提升,不过好的一点是开始阅读原版书籍了。至于看过的电影、剧集、番剧、书籍,听过的歌等等,在博客的补完页皆有记录,就不在此过多赘述了。有几部好莱坞大片是在日本影院看的,一边听着英语一边看着日语字幕的体验很是新奇。今年只带了 MacBook 赴日,所以没有怎么玩过游戏,倒是回坑了明日方舟(突然想起也是时候该打一打这一期的领航者合约了)。

愿 2026 的自己,依旧热烈,依旧满怀期待。

在 KOReader 上显示直排文本

2025-11-09 16:30:00

为了持续精进日语水平,也为了一并练习阅读直排文本时的速度,在下最近开始了阅读日文原版轻小说的计划。虽然在下手头上不缺纸质的阅读材料,但是作为一名不折不扣的电子书爱好者,电子版的轻小说自然也是不可缺少的。目前在下在电脑和手机上使用能够做到多端同步的 Readest 作为电子书的阅读器,而 Kindle 则几乎只剩下了 KOReader 这一唯一的选择。值得称道的一点是,由于 Readest 支持与 KOReader 同步服务器同步阅读进度,从某种程度上,也算打通了 Kindle 与主流设备之间的电纸书阅读体验壁垒(直接使用亚马逊 Kindle APP 确实是一种方案,但是原生不支持 EPUB 格式的问题是在下所不能接受的)。

不过,当在下在尝试把直排电子书导入 Kindle 阅读时,却发现了一个重大问题,KOReader 似乎并不支持显示直排文本,原来的直排格式只能以普通的横排文本的格式显示,导致好不容易打通的阅读体验壁垒又重新出现了。

好在,对直书有需求的电子书阅读者显然远不止在下一个。早在电子书刚刚起步阶段,相当一部分电子书阅读器也同样不支持直排文本的显示。对此,彼时的主流解决方案是直接将文字的显示方向旋转 90 度(一般是逆时针方向),然后把设备也一样横过来阅读,就这样实现所谓的「伪直排」阅读。然而在软件层面实现旋转文字的显示方向,比起直接支持直排文本来说显然更加复杂,直接简单粗暴地旋转显然不可行——那样的话,一些本不必要旋转的标点符号也会跟着一起旋转,比如省略号……或是直角引号「」。因此,有必要特意为此制作一套旋专用于「伪直排」阅读的字体。

制作「伪直排」字体#

原本修改字体是一件非常麻烦的事情,好在早有前人用 python 写了这个现成字体旋转工具 tategakifont 可供在下使用,此工具不仅能靠一行命令完成字体制作,还已经提前写好了相应的旋转规则,确保所有字符都被正确地旋转。

项目至少需要 Python 3.8.10 以及 FontForge 20230101 或更新的版本,在使用前需提前安装好运行环境。

随后,将项目文件克隆到本地,进入本地项目目录,把用于制作的原字体文件也拉进项目根目录,并在终端内运行以下命令,将 inputoutput 这两个字段分别替换为用于制作的原字体文件名称和拟定的经处理后的新字体文件名称:

python3 main.py input output

等待一会之后,「伪直排」字体就被制作好,躺在项目根目录当中了。

更改字体的 Family Name(可选)#

如果想在 KOReader 上同时使用原字体与经过处理后的「伪直排」字体,则需要更改「伪直排」字体的 Family Name。

由于 KOReader 会将 Family Name 相同的字体合并为一个选项,导致选择时无法指定到底是用原字体还是「伪直排」字体显示。

如果使用的是带有图形界面的字体编辑工具,那么直接想办法找到字体信息的编辑界面,将带有 Family Name (ID 1) 按照自己的意愿修改之即可。至于 Subfamily Name (ID 2)、Full Name (ID 4) 和 PostScript Name (ID 6),tategakifont 在制作新字体文件的时候会自动修改,因此一般不需修改,以防万一可以检查之。

由于在下只是装了一个 FontForge 的命令行版本,并不具有图形界面,所以具体操作起来比起图形化操作更加复杂一些,使用了基于 Python 的字体处理库 fonttools 实现。

直接在 tategakifont 的目录下创建一个虚拟环境并激活。

{% tabs 创建 Python 虚拟环境并激活 %}

python3 -m venv font_env
source font_env/bin/activate
python3 -m venv font_env
font_env\Scripts\activate.bat
python3 -m venv font_env
font_env\Scripts\Activate.ps1

{% endtabs %}

随后安装 fonttools 库。

pip install fonttools

再使用 ttx 工具将「伪直排」的字体文件转换为 XML,-t name 参数告诉 ttx 只转换包含名称信息(Name Table)的部分,这样生成的 XML 文件会小很多,方便编辑。将 your_font_file.ttf 改成「伪直排」字体的文件名称。

ttx -t name your_font_file.ttf

XML 文件在根目录生成后,随便用一个文本编辑器打开,按照自己的意愿修改带有 nameID="1" 部分的 namerecord 字段后保存即可。

最后,使用 ttx 命令将 XML 重新编译回字体文件,将 your_font_file.ttfyour_font_file.ttx 改成对应文件的文件名称。

ttx -m your_font_file.ttf your_font_file.ttx

至此,「伪直排」字体的 Family Name 修改完毕。

KOReader 直排补丁#

直接使用「伪直排」字体已经能达到阅读直排文本的目的了,但是由于仅旋转了字体,而电子书阅读器的界面却没有跟着一起旋转,因此在使用时,操作阅读器界面就会变得非常难受。此外,翻页逻辑也没有被一并更改,依旧需要像看横排书籍一样,从左至右翻页而非一般阅读直排书籍时的从右至左翻页,阅读体验依旧不完美。

去年,KOReader 的其中一名开发者在用户提出的关于日语直排书籍支持的 issue 中,针对此问题发布了一个补丁,效果是当文档的排版规则被设置为日语时,会自动将阅读器的文字部分的画面整体向顺时针旋转 90 度,这样一来,配合上向逆时针旋转 90 度的「伪直排」字体,可以完美地在 KOReader 上做到直排文本的显示。此外,补丁也适配了直排书惯用的从右至左的翻页方向。作者之后将其在 Github Gist 重新发布,比起在 issue 中发布的版本,主要修复了跨页选择文本的问题。

直排补丁的使用方法很简单,首先,前往此处下载补丁。

重命名文件,把原文件的 .txt 删除,使其扩展名变为 .lua,随后找到 KOReader 目录,将其放到 /koreader/patches 下,如果没有 patches 文件夹,则需要手动创建。

最后,在 KOReader 中打开直排书籍,在设置中更改排版规则为日语,再把字体换成制作好的伪直排字体即可。

虎落平阳:TNO 美国罗伯特·F·肯尼迪线·前篇

2025-05-05 17:35:00

NOTE

封面来源:The New Order: Last Days of Europe

NOTE

此文章由铁血幼儿园指挥官·威权壬(存疑)·P 社战犯·我不是二刺螈さん荣誉撰稿。

人民必须知道他们的总统不是骗子。People have got to know whether or not their president is a crook.我不是骗子,Well, I’m not a crook.我拥有的一切都是应得的。I’ve earned everything I’ve got.
理查德·尼克松Richard Nixon

TNO 世界观速览:美国版#

1940 年,由于受到苏联布哈林政府的失败影响(详见《柏林春晓:TNO 德国施佩尔左线》一文中「假如轴心国赢得了二战:TNO 世界观速览」的说明,由于版本更迭,两版世界观存在出入),政府调控经济的模式在美国遭到普遍质疑,时任美国总统富兰克林·罗斯福担心再次参选可能会摧毁他的政治遗产,因而决定不再参与他的第三次大选。于是,共和党人托马斯·杜威以微弱的优势战胜对手,入主白宫。为了回报孤立主义者的鼎力支持,杜威宣布美国将在世界大战中保持中立,并着手逐步撤销罗斯福政府的新政,这些决定最终改变了世界线:保守的经济政策导致美国的经济重新陷入停滞,而珍珠港事件也彻底击碎了孤立主义者的美梦。当美国仓促应战时,欧洲几乎已尽入轴心国之手,仅仅只得到了冰岛和法罗群岛作为安慰奖。尽管欧洲尽失,但杜威仍然凭借太平洋战场的战果取得了 1944 年大选的胜利。然而,很快杜威的政治生涯和美国在太平洋战场取得的优势便随着珍珠港核爆一起烟消云散。

由于杜威政府在二战中的彻底败北,共和党在 1948 年大选中大败。民主党人,国际主义者德怀特·艾森豪威尔旋即走马上任,他主张美国应当重拾自己的昭昭天命。很快,美国便宣布全面禁止与共荣圈和团结协定成员国的贸易,开启了属于 TNO 世界的冷战。然而,由于孤立主义者和建制派的阻挠,艾森豪威尔政府的政策收效甚微。另一边,出于对建制派不作为的愤怒和二战失败的不甘,大批极右翼政客从共和党出走,重建了国民党并参加了 1952 年大选。尽管艾森豪威尔仍设法在 1952 年大选中艰难取胜,但总统与国会的矛盾愈演愈烈,使其难以兑现自己的竞选承诺。

尽管艾森豪威尔任内几乎没有留下什么政治遗产,民主党和共和党却仍然遵循历史惯性,选择提名温和派政客参与总统大选,这无疑助长了美国民众对于建制派能力的怀疑。尽管又一位民主党人,建制派人士埃斯蒂斯·基福弗在 1956 年总统大选中得胜,极端主义党派如进步党、国民党等依旧凭借选票成功打入国会,慢慢搅动起早已是一潭死水的美国两党政治。极端派们虽然政见往往大相径庭,但是却有一个明确的共识:联合起来,打败建制派,重塑美利坚。在这一共识的推动下,国家进步公约(NPP)诞生了。出于对极端派颠覆美国政治格局的恐惧,共和党和民主党逐渐越走越近,最终形成了代表建制派的共民联盟。共民联盟首战告捷,共和党人理查德·尼克松联手民主党人约翰·F·肯尼迪在 1960 年大选中得胜,似乎标志着建制派在美国的统治地位仍将持续。

与其说 NPP 是一个政党,不如说它是一个松散的联盟。它聚集了一批不为建制派或主流社会观点接纳的奇人异士:有主张种族隔离的,也有主张种族融合的;有主张全球出击的,也有主张完全孤立的;有社会主义者,也有国家社会主义者……复杂的构成使得 NPP 的内耗极其严重,这也是他们 1960 年大选大败而归的原因之一。然而,只要建制派无法解决美国的沉疴顽疾,NPP 对于建制派的威胁就永远不会消退。

与成天鸡飞狗跳,内斗不止的 NPP 相比,代表建制派的共民联盟更加团结。但温和的政治主张意味着共民联盟无法开展激进的变革,倘若总统一意孤行一心求变,则共民联盟的政治团结将会遭受严重的破坏。

昔日的美国因为秉持孤立主义而与其他自由国家一道成为二战中的败者,如今在共民联盟的领导下,美国重振旗鼓,将要领导其他的自由国家一道从新世界启程与日本和德国争夺世界霸权,自由国家组织(OFN)因此成立,只是美国究竟是代表人类文明的灯塔,还是披着民主外衣的帝国,犹未可知。

1962 年的美国,内有极端势力步步紧逼,外有德国日本虎视眈眈。美利坚合众国能否否极泰来,令自由火炬熊熊燃烧;抑或改变航向,坠入深渊……这一切,皆将由接下来的这十年时间来一一定夺。

谎言与背叛:尼克松任期#

理查德·尼克松的中立的政治立场,使得他成为了首位来自公民联盟的美国总统。在他的统治下,美国将延续积极的对外干涉政策,希望将更多国家纳入自由世界的大家庭中。但是,尼克松也绝非恪守民主精神的卫道士,为了对抗影响力逐渐变强的 NPP,调查和窃听,甚至直接进行政治迫害成为了他光辉外表之下的黑暗阴影。

而在种族平等这个几乎全美关注政治议题上,尼克松为了讨好南方选民以及共和党内的迪克西派,不得不保持不置可否的态度。然而这种首鼠两端的表态不仅没能阻止 NPP 夺取南方各州,也很快惹恼了北方的民权活动家们,因种族问题引发的暴力冲突和游行示威不断蚕食着美国的稳定度。尼克松装鸵鸟的日子不会太长久,很快他便要在废除或维持种族隔离中做出自己的选择。

接下来,美国将会执行自己的干涉政策。由于 TNO 的设定,各国无法自由地加入军事同盟,也不得自由地向其他国家派遣志愿军,更不能自由地造宣称开战,取而代之的是一套内置的外交系统:德美日可以通过此系统干涉其他国家的冲突,并依最后的结果得到奖赏或惩罚。第一个美国可以入局的冲突是马来亚内战,马来亚半岛的日本合作政府自 1957 年崩溃以来,北部的抗日游击队和南部的日本帝国第 25 军便陷入到了长期的拉锯战中。虽然对共产党没有什么好感,但在马来亚建立一个亲美政权将为 OFN 在共荣圈中心取得一个珍贵的落脚点。至于如何在新生的马来亚建立一个亲美政权,这就是 CIA 需要考虑的事了。

不过,美国在马来亚的胜利给尼克松带来的喜悦没几天就被持续升温的种族议题给冲散了:马丁·路德·金的著名演讲将种族隔离制度再度推向风口浪尖;而在国会,高呼「州权神圣不可侵犯」的保守派议员与坚持人人平等理念的进步派议员吵作一团。最终,对尼克松保持缄默的行为感到失望的副总统约翰·肯尼迪在不知会尼克松的情况下独走,将自己制订的民权法案交予国会并获审通过。但或许是提防肯尼迪的影响力过大,又或者是不愿意太得罪保守派议员,尼克松最终否决了该法案,这导致大量民主党进步派党员加入 NPP 进步党。

在否决民权法案,暂时压制了种族议题的争论之后,尼克松继续将目光投向海外:臭名昭著的独裁者「公羊」拉斐尔·特鲁希略统治多米尼加已二十年有余,凭借着三头同盟和团结协定的支持,特鲁希略有恃无恐。美国对于特鲁希略的存在深恶痛绝,古巴和墨西哥也希望能铲除特鲁希略。现在机会出现了,三头同盟因为内部的积怨宣告解散,团结协定因为希特勒的昏迷陷入混乱,是时候把公羊送入地狱,让多米尼加回归自由世界了。

在多米尼加革命阵线取得阶段性胜利之后,白宫将在彻底清除原多米尼加残党与支持建立多米尼加联合政府之间做出选择:前者符合道义,也更契合其他美洲国家的愿望,但是新生的多米尼加有着倒向社会主义的风险,这将极大地助长海地本就难以控制的社会主义叛乱;后者虽然宽恕了曾经的纳粹分子,但是可以保证将多米尼加共和国转变为亲美政府。

与此同时,法属马达加斯加崩溃的报告也被呈至白宫。马达加斯加名义上由法国派遣殖民总督进行管理,实际上其真正的主人是德国国防军。德国人在当地大肆奴役当地人,攫取马达加斯加的资源,还在当地修建海军基地以保证德国对印度洋的影响力。然而随着日本支持的马达加斯加独立军起义,美国也找到了入局这一非洲最大岛屿的跳板。现在美国可以秘密地向叛军提供武器,并且增加叛军中亲美派系的影响力,如若成功,马达加斯加将在未来加入 OFN;然而,一旦美国的暗中行动被揭发,那么美国将再也无法影响马达加斯加的局势。

马达加斯加的战火尚未燃尽,菲律宾也紧接着发生了剧变。作为第二次世界大战中日本帝国的战利品之一,菲律宾的局势始终变幻莫测,日本合作者,共产党游击队和美国残兵反复争夺着这片区域。自从 1959 年以来,菲律宾政府军只能勉强控制马尼拉周边地区,但是随着北部的游击队和南部的美军同时发起进攻,菲律宾政府的崩溃似乎已成必然。

虽然菲律宾政府军在两面夹击之下很快败亡,但日本绝对不会坐视菲律宾这一南洋明珠脱离共荣圈,随着高山信武将军率领的第 14 军奉着不计代价勘定菲律宾叛乱的命令从吕宋岛登陆,菲律宾的局势迅速激化。这也给了美国加码菲律宾内战的机会,在赶走日本人之后,美国将可以通过为期半年的重建计划在菲律宾扶持一个亲美政府。

海地,其政治局势在被美国军事占领之后便长期受美国操纵,现任总统路易·德茹瓦更是彻头彻尾的顶级买办,在他统治下海地的百姓可谓生活在水深火热之中。不断积聚的民族主义情感以及尖锐的阶级矛盾在海地孕育出了强大的社会主义游击队,腐败横行的海地政府对乡间的游击队束手无策,若没有美国的援助,海地政府很快将会被游击队推翻,美国在加勒比海地区的影响力也有可能因此大受打击。因此,华盛顿一声令下,源源不断的美元、武器和军队开始送往太子港。

1963 年对于全世界来说注定是多事之年。在东亚,安田财团的崩溃引发了全共荣圈的经济危机;在欧洲,随着阿道夫·希特勒的死亡,德国及其专员辖区很快陷入到全面战争中,旧大陆再度陷于战火。而就在这一年快要结束之时,来自开普敦的急报将全世界的目光吸引到了这处前英国殖民地上。南非在二战中早就被德军吓破了胆,在德国挺进前葡萄牙殖民地莫桑比克和安哥拉时便直接滑跪,交出了纳米比亚。在之后的二十年里,南非一直在 OFN 和团结协定之间如履薄冰。但德国人并没有因为南非的懦弱而放弃征服南非的计划,南非的布尔人群体也早就看不惯龟缩在开普敦的英裔贵族,虽然德国内战尚未结束,但东非专员辖区专员许蒂希决定独走,指挥在非洲的国防军向南非猛攻。

对于美国来说,帮助南非对 OFN 回到非洲的计划大有裨益,而尼克松的想法则更加激进:如果不仅能保住南非,还能趁着德国内乱之际反攻并解放德国在非洲的殖民地,岂不是能大大扩展 OFN 在非洲的地盘?因此,在尼克松的运作下,OFN 开始全面动员,大批军队被调集至南非。然而,这几个非洲专员辖区可不比几座小岛,想要达成此目标,不仅要付出大量的人力和钱财,而且几乎必然面临一场旷日持久的战争。此外,当美国民众发现这个盛行种族隔离的南非绝非什么自由国家,而美军也绝非什么正义之师的时候,如何才能说服国内继续向非洲用兵,也将成为一个巨大的问题。

正当 OFN 军队在非洲前线与敌军酣战之时,来自伦敦的求助信也被送上了坚毅桌。在二战期间,尽管等来了美国的参战,英国最终还是惨败于德国之手。然而并不是所有的英国人都甘愿接纳这一屈辱的事实:游击队「女王陛下最忠诚的抵抗运动」(HMMLR)多年来一直活跃在伪政府的眼皮之下,随着德国崩溃,国防军离开英国,HMMLR 抓住了这一千载难逢的好机会,一举将伦敦的合作政府赶出了英国。但是现在还不是庆祝的时候,随着德国的内战尘埃落定,大日耳曼尼亚得以腾出手来解决这群英国的叛匪,新生的自由不列颠随时都有被扼杀的风险。英国之于 OFN 意义非凡,因为 OFN 大多数成员国都是前英属殖民地,而且保住英国也预示着 OFN 将有机会重返旧大陆。于是,美国和德国在英吉利海峡的对峙开始了,胜利者将能得到英国,然而若双方都互不相让的话,全面战争将可能一触即发,世界都将陷于核子烈焰之中……

正当尼克松在白宫对自己任内的外交成果沾沾自喜之时,一个足以让他的政治生涯提前结束的危机正在悄然形成。尼克松在 1960 年大选时曾出于对 NPP 的忌惮,决定进行种种间谍行动,最终以不义的手段赢得总统大选。虽然即位之后,尼克松便开始极力销毁或掩盖这些秘密,但是这些秘密还是被媒体得知。一开始,尼克松凭借着公民联盟在参议院占有多数席位而免于弹劾,但是随着事件的发酵和多方势力的推波助澜,尼克松的政治盟友们开始一个一个地与他划清界限。最终,在确认自己已回天乏术的情况下,为了避免落得最后彻底身败名裂的下场,尼克松无奈宣布辞职,由副总统约翰·肯尼迪接替他的位置。

戛然而止:约翰·肯尼迪和麦科马克任期#

尼克松在一片骂声中黯然下台,副总统约翰·F·肯尼迪走马上任。与在民权议题上唯唯诺诺的保守派尼克松不同,肯尼迪是众所周知的自由派,他对于南方种族隔离政策的厌恶和联邦至上的理念也是人尽皆知。现在,肯尼迪将要行使自己意外得到的总统大权,将美国打造成更加平等,博爱的国家。

然而肯尼迪的征程尚未开始便在意外中彻底结束,他的自由倾向激起了南方的种族主义者的愤恨和恐惧,正当肯尼迪在达拉斯举行自己的竞选集会之时,一颗饱含仇恨的子弹贯穿了他的大脑。

肯尼迪遇刺之后,众议院议长约翰·麦科马克在仓促之中走马上任。短短几个月之内,美国政局风起云涌,先是总统尼克松在丑闻缠身中被迫辞职,又是副总统肯尼迪遇刺身亡,美国政府的公信力几乎跌入谷底,民众对于美式价值观的认同也接近破灭。在这种情况下,麦科马克不敢再有所作为,他现在唯一的任务,就是确保美国在接下来的几个月内不再有大事发生,然后就只能寄期望于下一任总统能救美国于水火之中。

约翰·肯尼迪之死对于美国进步人士来说是一个重大损失,对于他的弟弟,罗伯特·肯尼迪来说更是如此。两兄弟曾怀抱着革除弊政的心态来到华盛顿特区,但是如今尼克松倒行逆施,约翰·肯尼迪身首异处,靠共民联盟这帮温和的建制派,美国的现状怎会有好转的可能?怀揣着这样的心态,罗伯特·肯尼迪宣布脱离民主党,加入以民权法案被否决为契机,影响力与日俱增的 NPP 进步党团,并凭借其在全美的声望被选为 1964 大选 NPP 的总统候选人。

随着 1964 年大选在绝望与激烈并存的氛围中开展,最终结果出人意料:来自 NPP 进步党团的罗伯特·F·肯尼迪险胜对手,赢得了总统之位。同时,NPP 在参议院的席位首次超过了共民联盟,建制派最终还是失去了美国民众的信任。「鲍比」·肯尼迪在就职典礼上发誓:要继承已故兄长的遗愿,将美国建设成更加平等的国家。然而赢家不止他一个人,信奉白人至上主义的 NPP 国民党团显然不会轻易让总统施展自己的手脚,约翰·肯尼迪的死亡也提醒着他一意孤行的最终下场……

烟火·乙巳

2025-02-02 20:20:00

NOTE

金波银浪任逍遥,财源广进乐陶陶,澄沨的漫游茶记恭祝阁下蛇年大吉,新春欢洛!