阅读视图

发现新文章,点击刷新页面。

将 LineageOS 20 升级到 LineageOS 21

我手机用的系统是开源的 LineageOS 20(Android 13),跨版本升级到 LineageOS 21(Android 14)需要用电脑手动操作。因为怕操作失误导致无法开机,所以想着先备份资料,但我懒得备份资料,于是好几个月没升级。今天就来升级了。

备份 #

虽然升级 LineageOS 不会清空储存空间,但为了保险起见,我按照自己的需求备份以下内容:

  1. 微信聊天记录
  2. 图片
  3. 电子邮箱账户截图
  4. 闹钟截图
  5. 应用列表

升级 #

按照 Upgrade LineageOS on lisa | LineageOS Wiki 的步骤,安装 LineageOS 21、重启到 Recovery、安装 Google Apps、重启。

这里碰到一个奇怪的问题:手机通过数据线直接插到笔记本电脑的 USB 口,用 fastboot 可以检测到设备,但安装新系统时会报错。数据线插到 USB 集线器才行。

感受 #

升级过程比我预想的简单。系统正常运作,所以清除了前面的备份。目前遇到两个问题:状态栏的快捷设置在亮色模式下仍然是暗色;Fcitx5 输入法底下的导航栏不见了,将「导航栏背景」设置为「跟随键盘背景色」即可解决。

如果你也要升级 LineageOS,不要照搬我的步骤,要遵循 LineageOS Wiki 的步骤,不同设备的升级步骤可能有差异。

开放的心态

在网上看到有人争论同类事物的好坏(比如:Vim 和 VS Code、Arch linux 和 Ubuntu),我认为没有必要去争。纠结哪个最好容易导致无尽的争吵。没有完美的工具,我们应该去思考工具的特点和适用场景。两个工具适用场景相似时可以先随便选一个,不要追求完美,适合就继续用,不适合就换另一个。

拿厨刀举例,主厨刀(chef’s knife)和切片刀哪个好?这个问题没有绝对的答案。

主厨刀
切片刀

主厨刀更轻更小,刀尖有弧度。刀尖有弧度就可以用摇刀切(rock chop),适合切蒜末。

切片刀更重,用它切菜时更流畅,使用者更省力。切片刀更宽大,可以把食材拍扁,还可以把切好的食材铲起来倒入锅中。

所以哪把刀好还是得看使用者的偏好,如果你喜欢轻巧就用主厨刀,喜欢功能多就用切片刀。

当然其实这两把刀都能切蔬菜和肉,不是很了解的情况下任选一把即可。选其他工具也一样,没实际用过就感受不到细微的差别,与其纠结,不如先随便挑一个用着。


图片出处:

冷泡茶教程

冷泡茶是用低温水泡的茶,苦味比热泡茶淡,有清凉感。

材料与工具 #

  • 茶叶(红茶、绿茶等)
  • 水壶
  • 冰箱

流程 #

  1. 茶叶与冷水的重量比例为 1:50,将茶叶与冷水加到到水壶,关闭盖子。
  2. 将水壶放入冰箱冷藏室,泡 4~8 小时。可以睡前泡,这样第二天早上就能喝了。

补充资料 #

QWERTY 键盘标点符号的中英文名称

AmE 表示 American English(美式英语),BrE 表示 British English(英式英语),表格的空白表示没有对应名称。

标点 英文 中文
~ tilde 波浪号
! exclamation point (AmE) / exclamation mark (BrE) 感叹号
@ at sign / at symbol
# hash / pound sign / number sign 井号
$ dollar sign 美元符号
% percent sign 百分号
^ caret 脱字符
& ampersand / and sign
* asterisk 星号
( ) parenthesis (AmE) / bracket (BrE) / round bracket (BrE) 圆括号
- hyphen / minus sign 连字符/减号
+ plus sign 加号
` backtick/backquote/grave 反引号/重音符
_ underscore 下划线
= equal sign (AmE) / equals sign (BrE) 等号
{ } brace / curly bracket 花括号
| verticle bar / pipe 竖线/管道
[ ] square bracket 方括号
\ backslash 反斜线/反斜杠
: colon 冒号
" double quote / double quotation mark 双引号
; semicolon 分号
' apostrophe / single quote / single quotation mark 撇号/单引号
< less-than sign 小于号
> greater-than sign 大于号
? question mark 问号
, comma 逗号
. period (AmE) / full stop (BrE) 句号
/ slash / forward slash (正)斜线/(正)斜杠

参考资料:Wikipedia, the free encyclopedia

少囤草稿,尽快发布

笔记软件里面的草稿越来越多,但是发布的文章却越来越少了。造成这个情况的原因有:用于写博客的时间少了、对文章的要求过高。囤着草稿是不好的,写好的文章应该发出来,为了帮助自己和他人。

刚写博客那会,我对文章内容没有太高要求,就是想着写好后几天内改几次(吐槽:这要求还不高吗),力求通俗易懂。后来写作要求提升了两次。

第一次提升要求是因为我查 Linux 资料时经常看 ArchWiki。ArchWiki 的内容又新又全面,而且注册个账号就可以贡献内容,我自己也贡献了一些内容。在这个过程中我觉得知识应该像 ArchWiki 那样,集中在一个地方,每个话题都有单独的页面,还方便大家贡献。慢慢我就不想写那些别人写过的内容,除非我能写得更好。能查到的内容就没必要写了。这就是程序员说的「Don’t repeat yourself」,不要重复产生信息。

第二次提升要求是因为我写出了排在谷歌搜索首位的文章,这给网站带来了持续的访问量,会有更多人看到我的博客,我很开心。在此之前,我一直觉得推广博客很难,到处去分享感觉就像滥发消息(spamming)。从此之后,我会优先写别人没写过的话题,写重复的话题尽量保证质量好到能排到谷歌搜索的第一页。

最近我刻意改变,将文章的重心放到帮助自己,降低要求。要求就两个:自己能读懂(可以对别人来说没那么通俗)、完整(不要写一半就发,写完初稿就可以发了)。发稿速度马上就上涨了,感觉非常好。

最近发布了四篇文章:

Grid 教程和 Flexbox 教程都是参考 CSS-Tricks 的教程写的。之前我也看过 CSS-Tricks 那两篇教程(CSS Flexbox Layout Guide | CSS-TricksCSS Grid Layout Guide | CSS-Tricks),但是自己写教程的过程中对两个 CSS 布局的理解更深入了,对我来说很有用。写好之后我哪里不懂也可以看自己写的教程,自己写的教程查起来更方便。写重复的话题可以加深理解,这也不意味着做复读机,我在写的过程中会有新的感悟,写出一些新内容。

写博客就像做开源项目,要让自己感觉舒服,对自己有用,这样才容易坚持。

菜谱:酱油蒜香炒蛋

材料 #

  • 蒜末
  • 酱油

步骤 #

  1. 将蛋打入碗中,不要搅拌
  2. 加酱油,搅拌均匀蛋黄和蛋清
  3. 加蒜末
  4. 下锅前搅拌
  5. 煎蛋或者炒蛋

备注 #

  • 可用鸡蛋或者鸭蛋,混蛋也行
  • 可用刀将蒜头切成蒜末,越碎越好
  • 搅拌蛋后再加酱油就看不清加了多少酱油
  • 蒜末会沉淀,所以下锅前搅拌

用柠檬酸和热水去除电热水瓶和保温瓶的水垢

柠檬酸是天然的清洁剂,可去除电热水瓶和保温瓶内的顽固水垢。它的用法是先浸泡,后清洗。如果水垢未完全清除,可以重复上述步骤。

材料 #

  • 柠檬酸除垢剂

电热水瓶浸泡方法 #

  1. 倒入冷水和柠檬酸(用量请参考说明书)。
  2. 煮沸后继续浸泡 30 分钟。

保温瓶浸泡方法 #

  1. 先倒入热水,再倒柠檬酸。
  2. 浸泡 3~4 小时。

清洗方法 #

电热水瓶和保温瓶的清洗方法是一样的。

  1. 倒掉混合液。
  2. 用清水冲洗。
  3. 如果冲洗后还有水垢,可以用厨房抹布擦。如果手无法伸入瓶内,可以用筷子抵住抹布擦拭。

CSS Grid 布局教程

CSS Grid 是二维布局方法,也就是用竖线和横线将内容划分成格子,像棋盘一样。本文只介绍常见用法,要了解全部用法请看 MDN Web Docs。推荐大家看完后做文末提到的习题。

概念 #

网格容器(Grid Container)、网格项(Grid Item) #

display: grid | inline-grid 使元素变成网格容器,其子元素叫网格项(其他后代不算),按照网格布局排列。下面代码的 .container 是网格容器,.item 是网格项,.sub-item 不是网格项。

1
2
3
.container {
 display: grid;
}
1
2
3
4
5
6
7
<div class="container">
 <div class="item"></div>
 <div class="item">
 <p class="sub-item"></p>
 </div>
 <div class="item"></div>
</div>

网格线(Grid Line) #

划分网格的竖线(vertical line)或横线(horizontal line)。横线方向和书写方向一致(英文是从左到右),竖线方向是从上到下。同一条网格线可以有多个名称。

虚线是网格线

网格单元(Grid Cell) #

网格布局的最小单位,就像电子表格的单元格和棋盘的格子,相邻的 2 个竖线之间和相邻的 2 条横线之间的区域。1 个网格项可以使用多个网格单元。

网格轨道(Grid Track) #

2 条相邻网格线之间的区域,也就是 1 个横排(row)或者 1 个竖排(column)。

网格区域(Grid Area) #

由 4 条网格线划分的区域,也就是长方形,比如 1 个网格单位、4 个网格单位、6 个网格单位。

示例(A 表示网格区域):

1
2
A???
????
1
2
AA??
AA??
1
2
AAA?
AAA?

显性网格(Explicit Grid)、隐性网格(Implicit Grid) #

显性网格有固定数量的网格轨道,比如 3×3。如果此时加入额外的网格项,网格将自动添加 auto 尺寸的隐性网格轨道,原来的显性网格轨道加上自动添加的隐性网格轨道就是隐性轨道。只定义竖网格线也可以产生隐性网格。

fr(fraction)1 份可用空间 #

fr 表示网格容器的 1 份可用空间。

1
2
3
4
5
6
7
.container {
 display: grid;
 /* 3 个竖排,比例为 1:2:1 */
 grid-template-columns: 1fr 2fr 1fr;
 /* 3 个横排,第 1 横排为 30px,剩余横排比例为 1:1 */
 grid-template-rows: 30px 1fr 1fr;
}

minmax() 最大最小值 #

参考资料:minmax() - CSS: Cascading Style Sheets | MDN

minmax() 函数设置最小值和最大值。下面代码表示第 1 横排的尺寸最小 50px,最大 auto(根据内容自动扩大)。

1
2
3
.container {
 grid-template-rows: minmax(50px, auto) 1fr 1fr;
}

repeat() 函数 #

参考资料:repeat() - CSS: Cascading Style Sheets | MDN

repeat() 函数用于表示重复的网格轨道片段。

在线示例

1
2
3
.container {
 grid-template-rows: repeat(3, 1fr); /* 1fr 1fr 1fr */
}

在线示例

1
2
3
.container {
 grid-template-rows: 2fr repeat(2, 1fr); /* 2fr 1fr 1fr */
}

除了使用固定的数字,还可用 auto-fitauto-fill

网格容器的属性 #

网格容器可以使用以下属性。

  • display
  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • grid-template
  • grid-column-gap
  • grid-row-gap
  • grid-gap
  • justify-items
  • align-items
  • place-items
  • justify-content
  • align-content
  • place-content
  • grid-auto-columns
  • grid-auto-rows
  • grid-auto-flow
  • grid

display 设置容器 #

对元素使用,使其变成网格容器。

1
2
3
.container {
 display: grid | inline-grid;
}

值:

  • grid:生成 block 级网格容器
  • inline-grid:生成 inline 级网格容器

grid-template-columns、grid-template-rows,网格线名称与网格轨道 #

参考资料:

示例(在线版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<div class="container">
 <div class="item item1">1</div>
 <div class="item item2">2</div>
 <div class="item item3">3</div>
 <div class="item item4">4</div>
 <div class="item item5">5</div>
 <div class="item item6">6</div>
 <div class="item item7">7</div>
 <div class="item item8">8</div>
 <div class="item item9">9</div>
</div>
1
2
3
4
5
6
7
8
9
.container {
 border: 1px solid red;
 height: 400px;
 display: grid;
 /* 3 个竖排,比例为 1:2:1 */
 grid-template-columns: 1fr 2fr 1fr;
 /* 3 个横排,第 1 横排为 30px,剩余横排比例为 1:1 */
 grid-template-rows: 30px 1fr 1fr;
}

现在网格项排列成这样:

1
2
3
1 2 3
4 5 6
7 8 9

可以用 [] 定义网格线名称,用空格分隔多个名称。

1
2
3
.container {
 grid-template-columns: [column1-start] 1fr [column2-start] 2fr [column3-start] 1fr [column-end another-name];
}

grid-column-startgrid-row-start 可以改变网格项的位置,在线示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.container {
 display: grid;
 grid-template-columns: [column1-start] 1fr [column2-start] 2fr [column3-start] 1fr [column-end];
 grid-template-rows: 30px 1fr 1fr;
}

.item9 {
 grid-column-start: column2-start;
 grid-row-start: 2; /* 第 2 条横线 */
}

现在 .item9 占据了 .item5 的位置。

1
2
3
1 2 3
4 9 5
6 7 8

grid-template-areas 网格区域名称 #

参考资料:grid-template-areas - CSS: Cascading Style Sheets | MDN

grid-template-areas 以网格区域名称表示网格的结构。grid-template-areas 的优点是放置网格项时不需要用网格线(数网格线或者命名真的太痛苦了)。相同名称可以用多次,表示占用多个网格单元。英文句号 . 表示不使用此网格单元。grid-area 定义元素对应的网格区域名称。

grid-template-areas 会自动使用 -start-end 命名网格线。header 网格区域的起始网格线(横线与竖线)都是 header-start,终止网格线(横线与竖线)都是 header-end。同一条网格线可以有多个名称。

示例(在线版):

1
2
3
4
5
6
<div class="container">
 <header>header</header>
 <aside>sidebar</aside>
 <main>main</main>
 <footer>footer</footer>
</div>
 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
header,aside,main,footer {
 border: 1px solid green;
}

.container {
 border: 1px solid red;
 height: 400px;
 display: grid;
 grid-template-areas:
 "header header header header"
 "main main . aside"
 "footer footer footer footer";
 grid-template-columns: 1fr 1fr 1fr 50px;
 grid-template-rows: auto;
}

header {
 grid-area: header;
}
aside {
 grid-area: aside;
}
main {
 grid-area: main;
}
footer {
 grid-area: footer;
}

grid-template(grid-template-rows、grid-template-columns、grid-template-areas 的缩写) #

参考资料:

grid-templategrid-template-rowsgrid-template-columnsgrid-template-areas 的缩写。grid-template 不会重置隐性网格属性。

只设置 grid-template-rowsgrid-template-columns 的用法是用 / 隔开两者。

示例(在线版):

1
2
3
4
5
6
7
8
9
.container {
 display: grid;
 /* 横排比例 1:1:1,竖排比例 1:3:1 */
 grid-template: 1fr 1fr 1fr / 1fr 3fr 1fr;
 /* 等价于
 grid-template-rows: 1fr 1fr 1fr;
 grid-template-columns: 1fr 3fr 1fr;
 */
}

同时设置 grid-template-rowsgrid-template-columnsgrid-template-areas 的用法:

  1. 先写 grid-template-areas
  2. 在每横排右边写上尺寸
  3. 在最后的横排加上 / 和竖排的尺寸(/ 从下一行开始写也行)

示例(在线版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
.container {
 border: 1px solid red;
 height: 400px;
 display: grid;
 grid-template:
 "header header header" auto
 "main main aside " 1fr
 "footer footer footer" auto / auto auto 50px;
 /* 等价于
 grid-template-areas:
 "header header header"
 "main main aside"
 "footer footer footer";
 grid-template-columns: auto auto 50px;
 grid-template-rows: auto 1fr auto;
 */
}

row-gap、column-gap、gap 间隔 #

参考资料:

row-gap 表示横排之间的间隔,column-gap 表示竖排之间的间隔。gap 是前面两者的缩写,使用 1 个值表示横排间隔和竖排间隔一样,使用 2 个值分别表示横排间隔是竖排间隔。

示例:

1
2
3
4
5
6
.container {
 row-gap: 30px;
 column-gap: 10px;
 gap: 10px; /* 竖排间隔和横排间隔都是 10px */
 gap: 30px 10px; /* 横排间隔 30px,竖排间隔 10px */
}

以前这 3 个属性前面要加上 grid-,比如 grid-row-gap。带 grid- 前缀的属性已被弃用,浏览器为了保持兼容,仍然支持这些属性。

justify-items,网格项的 inline 轴(横轴)对齐 #

参考资料:

justify-items 设置网格项 inline 轴(横轴)对齐方式,默认值为 stretch(占满网格单元宽度)。

1
2
3
.container {
 justify-items: start | end | center | stretch;
}

align-items,网格项的 block 轴(竖轴)对齐 #

参考资料:

align-items 设置网格项 block 轴(竖轴)的对齐方式,默认值为 stretch(占满网格单元高度)。baseline 表示按基线对齐。内容有多行时,first baseline 表示按照首行的基线对齐,last baseline 表示按照尾行的基线对齐。

1
2
3
.container {
 align-items: start | end | center | stretch | baseline | first baseline | last baseline;
}

place-items(align-items、justify-items 的缩写) #

参考资料:

place-itemsalign-itemsjustify-items 的缩写。使用 1 个值同时设置 2 个属性,使用 2 个值分别设置两个属性。

1
2
3
4
.container {
 place-items: center; /* 正中间 */
 place-items: start end; /* 右上角 */
}

justify-content,网格项整体 inline 轴(横轴)对齐 #

参考资料:

如果网格项的总尺寸小于网格容器的尺寸,网格容器会有多于的空白,此时网格项被放置于左上角(使用从左向右的语言)。justify-content 设置 inline 轴(横轴)的对齐方式。Flex 布局也有 justify-content,用法类似,参看 CSS Flexbox 布局教程#justify-content-主轴对齐(发布前看看这个链接对不对)。

在线示例

1
2
3
.container {
 justify-content: start | end | center | stretch | space-around | space-between | space-evenly; 
}

align-content,网格项整体的 block 轴(竖轴)对齐 #

参考资料:

如果网格项的总尺寸小于网格容器的尺寸,网格容器会有多于的空白,此时网格项被放置于左上角(使用从左向右的语言)。align-content 设置 block 轴(竖轴)的对齐方式。Flex 布局也有 align-content,用法类似。

在线示例

1
2
3
.container {
 align-content: start | end | center | stretch | space-around | space-between | space-evenly; 
}

place-content(align-content、justify-content 的缩写) #

参考资料:place-content - CSS: Cascading Style Sheets | MDN

place-contentalign-contentjustify-content 的缩写。用 1 个值同时设置两者,用 2 个值分别设置两者。

示例(在线示例):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.container {
 place-content: start end;
 /*
 align-content: start;
 justify-content: end;
 */
 
 place-content: center;
 /*
 align-content: center;
 justify-content: center;
 */
}

grid-auto-columns、grid-auto-rows 隐性网格轨道大小 #

参考资料:

如果网格项数量多于已定义的网格项数量,那么多出了网格项就位于隐性网格轨道。grid-auto-columns 设置竖向隐性网格轨道大小,grid-auto-rows 设置横向隐性网格轨道大小,两者默认值都是 auto

在线示例

1
2
3
.container {
 grid-auto-rows: 100px;
}

grid-auto-flow 自动放置算法 #

参考资料:

1
2
3
.container {
 grid-auto-flow: row | column | row dense | column dense;
}

grid-auto-flow 设置网格项的放置算法。

row(默认值):横向放置网格项,必要时添加新的横排。

1
2
3
1 2 3
4 5 6
7 8 9

column:竖向放置网格项,必要时添加新的竖排,在线示例

1
2
3
1 4 7
2 5 8
3 6 9

dense 关键词表示后面的元素可以移动到前面的空位,示例(在线示例):

1
2
3
4
5
6
7
8
<div class="container">
 <div class="item item1">1</div>
 <div class="item item2">2</div>
 <div class="item item3">3</div>
 <div class="item item4">4</div>
 <div class="item item5">5</div>
 <div class="item item6">6</div>
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
.item {
 border: 1px solid green;
}

.container {
 border: 1px solid red;
 height: 200px;
 width: 200px;
 display: grid;
 grid-template-columns: 1fr 1fr 1fr;
 grid-auto-flow: row dense; /* .item3 提前放置于 .item1 右边 */
}

.item1, .item2 {
 grid-column: span 2; /* 2fr */
}

grid( grid-template-rows、grid-template-columns、grid-template-areas、grid-auto-rows、grid-auto-columns、grid-auto-flow 的缩写) #

参考资料:

gridgrid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columnsgrid-auto-flow 的缩写。

创建显性网格时用法与 grid-template 一样。

创建隐性网格时有 2 种用法(左边设置横排,右边设置竖排,中间以 / 分隔):

  1. 显性横排,隐性竖排,grid-auto-flowcolumn<grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>?
  2. 隐性横排,显性竖排,grid-auto-flowrow[ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>

显性横排隐性竖排示例(在线版):

1
2
3
4
.container {
 /* 横排比例 1:2:1,按照竖排方向放置网格项,竖排尺寸 50px */
 grid: 1fr 2fr 1fr / auto-flow 50px;
}

隐性横排显性竖排示例(在线版):

1
2
3
4
.container {
 /* 隐性横排,按照横排方向放置网格项,竖排比例 1:2:1 */
 grid: auto-flow / 1fr 2fr 1fr;
}

网格项的属性 #

网格项可以使用以下属性:

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
  • grid-column
  • grid-row
  • grid-area
  • justify-self
  • align-self
  • place-self
  • subgrid
  • order

grid-column-start、grid-column-end、grid-row-start、grid-row-end 网格项位置 #

参考资料:

这几个属性通过网格线的起点与终点规定 1 个网格项的位置,默认值为 auto(自动放置)。span 数字 表示占用多少个网格轨道,不加数字时为 1。

示例(在线版):

1
2
3
4
5
6
7
8
<div class="container">
 <div class="item item1">1</div>
 <div class="item item2">2</div>
 <div class="item item3">3</div>
 <div class="item item4">4</div>
 <div class="item item5">5</div>
 <div class="item item-x">x</div>
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
.container {
 border: 1px solid red;
 height: 400px;
 display: grid;
 grid-template: 1fr 1fr 1fr / 1fr [col2-start] 1fr 1fr;
}

.item {
 border: 1px solid green;
}

.item-x {
 /* 从 col2-start 竖网格线到倒数第 1 条竖网格线 */
 grid-column-start: col2-start;
 grid-column-end: -1;
 /* 从第 2 条横网格线开始,占用 2 个横向网格轨道 */
 grid-row-start: 2;
 grid-row-end: span 2;
}

grid-column(grid-column-start、grid-column-end 的缩写)、grid-row(grid-row-start、grid-row-end 的缩写) #

参考资料:

grid-columngrid-column-start / grid-column-end 的缩写,使用 1 个值时只设置 grid-column-start

grid-rowgrid-row-start / grid-row-end 的缩写,使用 1 个值时值设置 grid-row-start

示例(在线版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.item-x {
 grid-column: col2-start / -1;
 grid-row: 2 / span 2;
 /*
 grid-column-start: col2-start;
 grid-column-end: -1;
 grid-row-start: 2;
 grid-row-end: span 2; 
 */
}

grid-area(grid-row-start、grid-column-start、grid-row-end、grid-column-end 的缩写) #

grid-area 有两个用法。一是 grid-row-start / grid-column-start / grid-row-end / grid-column-end 的缩写(吐槽:这个顺序不好读,-start 后面应该跟 -end);二是搭配 grid-template-area,使用名称指定位置。

示例(在线版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.item-x {
 grid-area: 2 / col2-start / span 2 / -1;
 
 /*
 grid-column: col2-start / -1;
 grid-row: 2 / span 2;
 
 grid-column-start: col2-start;
 grid-column-end: -1;
 grid-row-start: 2;
 grid-row-end: span 2; 
 */
}

justify-self,inline 轴(横轴)对齐 #

justify-self 设置 1 个网格项的 inline 轴(横轴)对齐方式,默认值是 stretch

1
2
3
.item {
 justify-self: start | end | center | stretch;
}

在线示例

1
2
3
.item4 {
 justify-self: center;
}

align-self,block 轴(竖轴)对齐 #

align-self 设置 1 个网格项的 block 轴(竖轴)对齐方式,默认是 stretch

1
2
3
.item {
 align-self: start | end | center | stretch;
}

在线示例

1
2
3
.item4 {
 align-self: end;
}

place-self(align-self、justify-self 的缩写) #

参考资料:

place-selfalign-self justify-self 的缩写,只使用 1 个值时同时设置两者。

示例:

1
2
3
4
.item4 {
 place-self: center; /* 正中间 */
 place-self: end start; /* 左下角 */
}

subgrid 继承网格容器属性 #

参考资料:Subgrid - CSS: Cascading Style Sheets | MDN

虽然 subgrid 不是属性,但用于网格项,所以列举于此。

示例(在线版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<div class="container">
 <div class="item item1">Item1</div>
 <div class="item item2">Item2</div>
 <div class="item item3">Item3</div>
 <div class="item item4">Item4</div>
 <div class="item item5">Item5</div>
 <div class="item item6">Item6, 4×4
 <div class="item6-1">Item6.1, 1×1</div>
 <div class="item6-2">Item6.2, 1×1</div>
 </div>
</div>
 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
30
31
32
33
34
35
.container {
 border: 1px solid red;
 height: 400px;
 display: grid;
 grid-template: 1fr 1fr 1fr / 1fr 1fr 1fr;
 gap: 10px;
}

.item {
 border: 1px solid green;
}

.item6 {
 border: 1px solid yellow;
 grid-area: 2 / 2 / span 2 / span 2;
 display: grid;
 /*
 用 subgrid 才能继承容器的 gap 属性,
 可以删掉下面两行代码看看差异 */
 grid-template-columns: subgrid;
 grid-template-rows: subgrid;
}

.item6-1 {
 border: 1px solid blue;
 /* 使用 .item6 的网格线编号,不要用 .container 的网格线编号 */
 grid-column-start: 2;
 grid-row-start: 2;
}

.item6-2 {
 border: 1px solid blue;
 grid-column-start: 2;
 grid-row-start: 1;
}

order 顺序 #

参考资料:order - CSS: Cascading Style Sheets | MDN

网格项默认按照源代码顺序出现。order 设置网格项的出现顺序,默认值为 0,可使用正数和负数。

示例(在线版):

1
2
3
4
5
6
.item1 {
 order: 1;
}
.item9 {
 order: -1;
}

待写内容 #

参考资料 #

图片出处 #

本文使用的图片出自 CSS Grid Layout Module Level 1#grid-concepts

练习 #

CSS BEM 命名规范入门教程

BEM(Block, Element, Modifier)是 HTML/CSS 类的命名方法,它可以让 HTML 和 CSS 代码更有条理。

概念与用法 #

一开始看不懂没关系,后面有示例。

  • block(块):可以独立使用的 HTML 元素(比如:<nav>),可以不包含 element。
  • element(元素):依附于 block 的 HTML 元素,无法独立存在(比如:<li>),前面要加上双下划线 __
  • modifier(修饰符):表示 block 或者 element 的状态和外观,前面要加上双连字符 --
  • 用单连字符 - 连接单词,比如:search-form
  • element 只属于 block,而不是另一个 element。错误写法:block__element1__element2,正确写法:block__element2
  • 使用 modifier 时,同时保留不含 modifier 的类名,比如:<a class="menu__link menu__link--active" href="/zh-cn/">主页</a>

HTML 示例 #

<nav> 元素是 block,它包含的 element 有 <ul><li><a>--active 是修饰符。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<nav class="menu">
 <ul class="menu__list">
 <li class="menu__item">
 <a class="menu__link menu__link--active" href="/zh-cn/">主页</a>
 </li>
 <li class="menu__item">
 <a class="menu__link" href="/zh-cn/posts/">文章</a>
 </li>
 <li class="menu__item">
 <a class="menu__link" href="/zh-cn/about/">关于</a>
 </li>
 </ul>
</nav>

CSS 示例 #

在线示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* 横向列表 */
.menu__list {
 display: flex;
 flex-direction: row;
 flex-wrap: wrap;
 justify-content: space-between;
 list-style-type: none;
 padding-inline-start: 0;
}

/* 加粗和当前页面匹配的链接 */
.menu__link--active {
 font-weight: bolder;
}

SCSS 示例 #

我更推荐用 SCSS,用父选择器 & 可以把 block 和 element 的样式都放在一起,这种结构可以清晰地展现它们的层级关系。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
.menu {
 // 横向列表
 &__list {
 display: flex;
 flex-direction: row;
 flex-wrap: wrap;
 justify-content: space-between;
 list-style-type: none;
 padding-inline-start: 0;
 }

 // 加粗和当前页面匹配的链接
 &__link {
 &--active {
 font-weight: bolder;
 }
 }
}

替代方案:原子式 CSS #

如果你觉得 BEM 太冗长或者难以维护,那你可以试试原子式1 CSS 框架(atomic CSS framework),比如:Tailwind CSSUnoCSS。这些框架会提供 utility(预定义的类)。开发者只需要写预定义的类名,不需要写 CSS 代码。以下是一些 Tailwind CSS 的 utility:

1
2
3
4
5
6
.flex {
 display: flex;
}
.flex-row {
 flex-direction: row;
}

用 Tailwind CSS 重写之前的 CSS 代码(在线示例):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<script src="https://cdn.tailwindcss.com"></script>
<script>
 tailwind.config = {
 corePlugins: {
 preflight: false,
 }
 }
</script>
<nav>
 <ul class="flex flex-row flex-wrap justify-between list-none ps-0">
 <li>
 <a class="font-bold" href="/zh-cn/">主页</a>
 </li>
 <li>
 <a href="/zh-cn/posts/">文章</a>
 </li>
 <li>
 <a href="/zh-cn/about/">关于</a>
 </li>
 </ul>
</nav>

补充资料 #


  1. atomic CSS 一般译为「原子化 CSS」,我认为这个翻译是错的。「化」表示状态变化,对应英文的「-ize」和「-ify」词缀,比如:净化(purify)、标准化(standardize)。atomic 可以拆分成 atom(原子)和 -ic(形容词后缀),所以我把 atomic 翻译成原子式,「式」表示形式、样式。atomic 也可以翻译成原子型,「型」表示类型、样式。 ↩︎

CSS Flexbox 布局教程

Flexbox(弹性盒子)是一维的布局方法,也就是在一条横线(row)或者竖线(column)上排列元素。推荐大家看完本文后做文末提到的习题

flex 容器的属性 #

flex 容器(flex container)的属性有 displayflex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-contentrow-gapcolumn-gapgap

flex 容器与 flex 项 #

以下的 section 元素包含了 3 个 article 元素。

1
2
3
4
5
<section>
 <article>Article 1</article>
 <article>Article 2</article>
 <article>Article 3</article>
</section>

要排列 article 元素,将它们的父元素设置为 flex 容器。

1
2
3
section {
 display: flex | inline-flex; /* inline-flex 表示容器是 inline 元素 */
}

在上述例子中,section 元素是 flex 容器(flex container),article 元素是 flex 项(flex item)。

flex-direction 方向、主轴、交叉轴 #

flex-direction 定义排列方向和主轴。

1
2
3
.container {
 flex-direction: row | row-reverse | column | column-reverse;
}
  • row(默认值):横向,和文字方向(dir)一致,如果方向是从左往右,那么就是从左往右排列子元素
  • row-reverse:和前者相反,从右往左
  • column:纵向,从上到下
  • column-reverse:和前者相反,从下到上

主轴(main axis)就是和 flex 项排列方向一致的轴,交叉轴(cross axis)则是与主轴垂直的轴。一定要分清楚方向和两条轴,在对齐 flex 项时会用到。

1
2
3
4
.container {
 display: flex;
 flex-direction: row;
}

上述代码表示从左到右排列 flex 项,主轴是从左到右,交叉轴是从上到下。

轴的图示

flex-wrap 换行 #

flex-wrap 控制是否换行,默认不换行。

1
2
3
.container {
 flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap(默认值):全部 flex 项排列成一条线
  • wrap:溢出时换行
  • wrap-reverse:溢出时换行,但后面的元素会排到前面

示例代码(在线示例):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<section>
 <article>Article 1</article>
 <article>Article 2</article>
 <article>Article 3</article>
 <article>Article 4</article>
 <article>Article 5</article>
 <article>Article 6</article>
 <article>Article 7</article>
 <article>Article 8</article>
 <article>Article 9</article>
</section>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
section {
 display: flex;
 flex-direction: row;
 flex-wrap: wrap-reverse;
}

article {
 width: 100%;
 outline: 1px solid green;
}

flex-flow(flex-direction 和 flex-wrap 的缩写) #

flex-flowflex-directionflex-wrap 的缩写,默认值为 row nowrap

下面两份代码效果一样:

1
2
3
4
section {
 flex-direction: row;
 flex-wrap: wrap;
}
1
2
3
section {
 flex-flow: row wrap;
}

justify-content 主轴对齐 #

justify-content 设置主轴的对齐方式。

1
2
3
.container {
 justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}

下面只介绍常用的值。

  • flex-start(默认):将所有 flex 项放到主轴的起点。如果主轴是 row(从左到右),那么所有 flex 项贴近左边。例子(. 表示空间):Item1Item2Item3......
  • flex-end:将所有 flex 项放到主轴的终点。例子:......Item1Item2Item3
  • center:将所有 flex 项放在主轴的中间。例子:....Item1Item2Item3....。
  • space-between:均匀分配 flex 项,每个 flex 项之间的距离一样,头部 flex 项贴近主轴开头,尾部 flex 项贴近主轴末尾,例子:Item1..Item2..Item3
  • space-around:均匀分配 flex 项,每个 flex 项的前后间隔一样,例子:.Item1..Item2..Item3.
  • space-evenly:均匀分配 flex 项,每个 flex 项之间的距离一样,头部 flex 项和主轴开头有一样的距离,尾部 flex 项和主轴末尾有一样的距离。例子:..Item1..Item2..Item3..

align-items 交叉轴对齐 #

交叉轴垂直于主轴。align-items 设置交叉轴的对齐方式。

1
2
3
.container {
 align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}

align-items 用法和 justify-content 类似,这里介绍一些不一样的值。

  • stretch(默认值):使 flex 项填满容器。
  • baseline:根据基线对齐,用于字体大小不同的 flex 项,图示

align-content 交叉轴对齐(仅用于多行 flex 项) #

align-content 设置多行 flex 项的交叉轴对齐方式,flex 项只有一行时(flex-wrap: nowrap;)无效,图示

1
2
3
.container {
 align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}

align-content 用法和 align-items 类似。

row-gap、column-gap、gap 间隔 #

如果在 flex 项上画横线和竖线,row-gap 表示横线的间隔大小,column-gap 表示竖线的间隔大小,gap 是前面两者的缩写,在线示例

1
2
3
4
5
6
7
8
.container {
 display: flex;
 flex-wrap: wrap;
 row-gap: 20px;
 column-gap: 5px;
 gap: 20px 5px; /* row-gap, column-gap */
 gap: 20px; /* row-gap 和 column-gap 都是 20px */
}

gap 只是设置最小间隔,使用 space-between 可以加大间隔。

flex 项的属性 #

flex 项(flex item)的属性有 orderflex-growflex-shrinkflex-basisflexalign-self

flexbox 没有 justify-self,参看 Box alignment in flexbox - CSS: Cascading Style Sheets | MDN#there_is_no_justify-self_in_flexbox

order 顺序 #

默认情况下,flex 项按照源代码出现的顺序排列。使用 order 属性可以改变顺序,默认值为 0,数字越大位置越后,可以使用负值(比如:-1)。如果多个 flex 项的 order 值一样,它们还是按原始顺序排列。

1
2
3
4
5
6
7
8
9
#item1 {
 order: 2;
}
#item2 {
 order: 1;
}
#item3 {
 order: -1;
}

图示:

1
item3 | item2 | item1

flex-basis 大小 #

flex-basis 设置 flex 项的大小,默认为 auto

1
2
3
.item {
 flex-basis: 50px;
}

flex-grow 增长 #

flex 容器有多余空间时,flex-grow 设置 flex 项的增长系数,默认为 0(不增长),负值无效。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.item1 {
 flex-grow: 1;
}

.item2 {
 flex-grow: 2;
}

.item3 {
 flex-grow: 1;
}

上面代码表示将多余空间(假设为 100px)均分为 4 份,.item1 的宽度增加 1 份(25px),.item2 的宽度增加 2 份(50px),.item3 的宽度增加 1 份(25px),在线示例

flex-shrink 收缩 #

空间不足时,flex-shrink 设置 flex 项的收缩指数,默认为 1(可收缩),0 表示不可收缩,负值无效。flex-shrink 的效果和 flex-grow 类似。

假设有 1 个 200px 宽度的 flex 容器,它包含 3 个 flex 项(每个宽度 100px,共 300px),此时有 100px 溢出的宽度。

1
2
3
4
5
6
7
.container {
 display: flex;
 width: 200px;
}
.item {
 flex-basis: 100px;
}

如果 flex 项总宽度减去 100px,那么就不会溢出,在线示例

1
2
3
4
5
6
7
8
9
.item1 {
 flex-shrink: 1;
}
.item2 {
 flex-shrink: 2;
}
.item3 {
 flex-shrink: 1;
}

上面代码表示把溢出的 100px 均分为 4 份。.item1 宽度减去 1 份(25px),变成 75px;.item2 宽度减去 2 份(50px),变成 50px;.item3 宽度减去 1 份(25px),变成 75px。

flex(flex-grow、flex-shrink 和 flex-basis 的缩写) #

flexflex-growflex-shrinkflex-basis 的缩写,默认为 0 1 auto。推荐使用 flex 代替那 3 个属性,它会自动使用合理的默认值。比如使用 flex: 1 设置 flex-grow: 1 时,flex-basis 会变成 0%。

flex 可以使用 1~3 个值,具体用法请看 flex - CSS: Cascading Style Sheets | MDN

使用 flex 可以轻松设置 flex 项的大小比例,在线示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
.container {
 display: flex;
 flex-direction: row;
 width: 100px;
}

.item1 { /* 25px */
 flex: 1;
}
.item2 { /* 50px */
 flex: 2;
}
.item3 { /* 25px */
 flex: 1;
}

align-self 交叉轴对齐 #

align-self 设置单个 flex 项的交叉轴对齐方式,用法和 align-items 一样,两者可以同时用。

习题 #

参考资料 #

2024-08-03 本站改动:使用 Yue 主题和 giscus 评论,post 目录改为 posts

本文列举了本站于2024年7月28日至2024年08月03日的改动。

  • 清理无用文件
  • 使用我写的 Yue 主题(感觉自己从几乎不折腾博客一下走到折腾博客的尽头了,用自己的主题太爽了,哈哈)
  • 讲 utterances 评论服务改为 giscus(终于可以回复评论了,不需要引用文字或者 @
  • post 文件夹改为 posts

改动很多,最好在 Git 仓库建一个分支搭配子域名(如 test.cyrusyip.org)测试,没问题再合并代码至主分支。修改网站要注意功能和链接(URL)变动,改了链接要修改文章内部链接、重定向、迁移评论。

清理无用文件 #

不再使用以下软件/服务:

  • blogdown
  • Netlify
  • Vercel
  • ……

删除相关文件,修订自述文件和 package.json

将主题换为 Yue #

先构建一次,保存起来

1
2
3
4
cd cyrusyip-blog
mkdir ~/Desktop/blog-builds
rm -r public; npx hugo # hugo 前面多了 npx 是因为我用 npm 安装 hugo
mv public ~/Desktop/blog-builds/jane

删除 Jane 主题和相关文件,重命名配置和中文内容文件夹。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 删除相关文件
rm -r assets layouts resources
git add --all
git commit --message 'chore: remove custom files related to jane theme'
# 删除主题
git submodule deinit themes/jane # 修改 .git/config
git rm themes/jane # 修改 .gitmodules
rm -rf .git/modules/themes/jane # 删除本地文件
git commit --message 'feat!: remove jane theme'
# 重命名
mv config.toml _config.toml
mv content/zh-cn content/zh-CN
git add --all
git commit --message 'refactor: rename to content/zh-CN and _config.toml'

安装主题。

1
2
git submodule add --depth=1 https://github.com/CyrusYip/hugo-theme-yue themes/hugo-theme-yue
git commit --message 'feat: add hugo-theme-yue'

写新配置,对照原来的配置(_config.toml)。删掉了 keywords、description、Google Analytics、Disqus、utterances,后面再加回来。

1
2
3
cp themes/hugo-theme-yue/exampleSite/hugo.yaml .
# 写好新配置后删除旧配置
rm _config.toml

构建,对比目录名和文件名变化,如果没变化表示 URL(链接)没变化。用 tree 命令列举两次构建的文件,复制到剪切板,使用 Diffchecker 对比。

1
2
3
4
5
rm -r public; npx hugo
# 旧主题
tree ~/Desktop/blog-builds/jane | wl-copy
# 新主题
tree ~/Desktop/blog-builds/yue | wl-copy

新主题编译的网站少了一些没用到的页码,这里无需处理。新网站还多了一篇 2021-01-29-python-calculate-utility-bills.Rmarkdown,这是 Rmarkdown 文件,不应该出现于此,在配置文件忽略它。

1
2
# hugo.yaml
ignoreFiles: ["\\.Rmd$", "\\.Rmarkdown$", "_cache$", "\\.knit\\.md$", "\\.utf8\\.md$"]

构建网站后再对比,没这个 .Rmarkdown 文件了。

对比:

  • 原主题编译的网站有 607 个目录,480 个文件,构建时间 750ms。
  • 新主题编译的网站有 398 个目录,354 个文件,构建时间 450ms。新网站关闭了 enableGitInfo,还没添加统计和评论功能(只是加脚本应该不太会影响构建时间)。

用肉眼对比新旧网站,看看有没有问题。看样式、文章数量、日期等。

添加本站原有的功能 #

  • Google Analytics
  • utterances
  • Disqus
    • 只在 cyrusyip.org 上面显示
    • 这次加上了多语言功能
  • 图片说明文字
  • 页脚
    • 社交媒体、Github、Stack overflow、Twitter
    • CC BY-NC-SA 4.0 协议
  • meta description
  • keywords(meta keywords 已过时,参看 Meta Keywords:是什么、为什么不 | Sukka’s Blog

将 utterances 评论改为 giscus #

另建一个站点测试会比较稳妥,但这次为了节约时间就直接改了。

giscusGitHub Discussions 驱动,功能比 utterances 强,支持多语言和回复评论。

转换步骤:

  1. 删除网站的 utterances
  2. 给相关 issue 打标签「Comments」,issue 不多我就直接在网页操作了,一次可以改一页,多的话用 gh issue edit 命令
  3. 开启 Discussion,新建类别「Comments」
  4. 测试 giscus 是否能新建讨论,标题是否正确
  5. 转换 issue(Comments 标签)为 discussion( Comments 类别),参看 Managing discussions - GitHub Docs#converting-issues-based-on-labels。页面显示「Open issues with label ‘Comments’ are being converted to discussions」,但是过了一两个小时都没反应,最后手动转换了。
  6. 创建 giscus.json 配置文件,限制域名,参看 giscus/ADVANCED-USAGE.md#origins
  7. 在 GitHub 卸载 utterances
  8. 把仓库名 blog-comment 改为 blog-comments,去 giscus 官网重新获取脚本(非必须步骤,这里存了超过一则评论,所以用复数 comments)

post 文件夹改为 posts #

之前用的 Even 主题Jane 主题 要求内容放在 content/post 文件夹,但是标签(/tags/)和类别(/categories/)用的是复数,我觉得这非常不协调。这次换主题终于可以改成复数 posts 了。

改了之后网站链接(URL)会变化,需要重定向旧链接、修改文章内链接、迁移评论,参考我之前写的文章(真是帮了大忙):

重命名文件夹 #

构建未修改的网站并保存。

1
2
3
cd cyrusyip-blog
rm -r public; npx hugo
mv public ~/Desktop/blog-builds/before

重命名文件夹。

1
2
mv content/en/post content/en/posts
mv content/zh-CN/post content/zh-CN/posts

预览并修改配置。

1
rm -r public; npx hugo server --navigateToChanged --bind 0.0.0.0
1
2
3
4
5
6
7
8
--- a/hugo.yaml
+++ b/hugo.yaml

- post: /post/:year/:month/:day/:slug/
+ posts: /posts/:year/:month/:day/:slug/

- pageRef: /post
+ pageRef: /posts
1
2
3
4
5
6
7
8
--- a/frontmatter.json
+++ b/frontmatter.json

- "path": "[[workspace]]/content/en/post",
+ "path": "[[workspace]]/content/en/posts",

- "path": "[[workspace]]/content/zh-CN/post",
+ "path": "[[workspace]]/content/zh-CN/posts",
1
2
git add --all
git commit --message "refactor: content/*/post -> content/*/posts"

关掉 Hugo 服务器,构建修改后的网站并保存。

1
2
rm -r public; npx hugo
mv public ~/Desktop/blog-builds/after

复制两个网站目录的结构到剪切板,用 Diffchecker 对比。

1
2
3
4
# 旧网站,Original text
tree ~/Desktop/blog-builds/before | wl-copy
# 新网站,Changed text
tree ~/Desktop/blog-builds/after | wl-copy

就只是 post 目录变成了 posts

1
2
3
4
5
- /en/post
+ /en/posts

- /zh-cn/post
+ /zh-cn/posts

修改文章内部链接 #

要将 [本站的某文章](/zh-cn/post/2021/01/01/hi/) 这样的链接改成 [本站的某文章](/zh-cn/posts/2021/01/01/hi/)。 获取包含链接的文件,并删掉不需要改的链接。

1
2
3
mkdir todo
rg '\[.*\]\(/.*\)' content --only-matching >> todo/internal-links
rg 'cyrusyip\.org' content >> todo/internal-links

链接记录节选:

1
2
3
content/zh-CN/posts/2021-06-19-ac2100-openwrt.md:[红米 AC2100 刷 breed 后刷回官方固件](/zh-cn/post/2022/10/16/ac2100-stock-firmware/)
content/zh-CN/posts/2021-08-30-raspberry-pi-4b-openwrt.md:[在 OpenWrt 控制树莓派 Argon Mini Fan](/zh-cn/post/2021/09/15/openwrt-argon-mini-fan/)
content/zh-CN/posts/2021-08-30-raspberry-pi-4b-openwrt.md:[树莓派 4B 超频教程](/zh-cn/post/2021/09/20/raspberry-pi4-overclock/)

自己手动改链接,改一条就删去一条记录。使用 hugo server --navigateToChanged 命令预览网站可以很方便地查看变化。

我一开始让 ChatGPT 写 Node.js 脚本帮我改,多番交流后它生成了一些不存在的链接,看来这个工作还是太难为它。

重定向 #

现在本站使用 Cloudflare Pages 构建,参考 Redirects · Cloudflare Pages docs 设置重定向。我有点搞不懂我之前写的一些重定向规则,所以要写好注释,未来的我会感谢现在写注释的我。

1
2
3
4
5
6
7
# static/_redirect
######################################################################
# Rename "content/{en,zh-CN}/post" to "content/{en,zh-CN}/posts"
# URL changes: /en/post/ -> /en/posts/ , /zh-cn/post/ -> /zh-cn/posts/
######################################################################
/en/post/* /en/posts/:splat 308
/zh-cn/post/* /zh-cn/posts/:splat 308

测试链接:

关闭评论 #

关闭 Disqus 和 giscus 评论,以免迁移时有读者留言。

迁移 Disqus 评论 #

参考教程:How to download, edit, and upload a URL Map CSV | Disqus

打开迁移工具,点击「Start URL mapper」->「you can download a CSV here」,去邮箱拿到下载链接,下载并解压。这个 CSV 里面的链接非常乱,有无评论的、带查询参数的(/?utterances=xxx)、失效链接。建一个 Git 仓库,把 CSV 文件放进去并提交,后面方便看改动。

修改 CSV,留下以 https://cyrusyip.org/zh-cn/posthttps://cyrusyip.org/en/post 开头的。

文件节选:

1
2
https://cyrusyip.org/zh-cn/post/2021/03/08/girls-day-womens-day-and-goddesses-day/
https://cyrusyip.org/zh-cn/post/2021/01/10/remove-odor/

在 Vim 执行 :%s/.*/&,&,现在每行都有两个一样的链接,提交改动。

1
2
https://cyrusyip.org/zh-cn/post/2021/03/08/girls-day-womens-day-and-goddesses-day/,https://cyrusyip.org/zh-cn/post/2021/03/08/girls-day-womens-day-and-goddesses-day/
https://cyrusyip.org/zh-cn/post/2021/01/10/remove-odor/,https://cyrusyip.org/zh-cn/post/2021/01/10/remove-odor/

执行 :%s/\v(.*)(post)/\1posts,现在把每行第二个链接的 post 改成 posts,提交改动。

1
2
https://cyrusyip.org/zh-cn/post/2021/03/08/girls-day-womens-day-and-goddesses-day/,https://cyrusyip.org/zh-cn/posts/2021/03/08/girls-day-womens-day-and-goddesses-day/
https://cyrusyip.org/zh-cn/post/2021/01/10/remove-odor/,https://cyrusyip.org/zh-cn/posts/2021/01/10/remove-odor/

把修改后的 CSV 文件上传到 Disqus 的 URL mapper。

迁移 giscus 评论 #

将标题的 post 改为 posts

示例:

1
2
- zh-cn/post/2024/04/05/i-hate-obscure-words/
+ zh-cn/posts/2024/04/05/i-hate-obscure-words/

GitHub CLI 不支持修改 Discussion,又得手动改了。

查看评论 #

这几篇文章有 Disqus 评论,打开看看是否有评论。

Discussions 里找几篇文章,打开看看是否有评论。

开启评论 #

可以看到评论,重新打开 Disqus 和 giscus。

菜谱:煎荷包蛋

材料与工具 #

  • 冷藏的鸡蛋(1 个约 51g)
  • 电磁炉
  • 精铁平底炒锅(已开锅)
  • 花生油(不要使用菜籽油这种低闪点的油,热锅后倒下去可能会着火)
  • 锅铲
  • 筷子
  • 计时器
  • 两个碗(一个装鸡蛋,另一个装少量水)

第一次煎蛋的流程 #

  1. 打蛋到碗里
  2. 打开计时器记录热锅时间(后面会用到),电磁炉开到最高档位(2200w)。用手沾一点点水甩入锅,如果直接蒸发就是温度不够,如果水珠弹跳说明温度够了,记下热锅时间,重置计时器,等水珠蒸发。
  3. 暂停电磁炉,倒油,摇晃锅使锅底都被油覆盖
  4. 倒蛋,马上调到 500W1,按下计时器
  5. 等大概 1.5 分钟。等待期间可用锅铲轻推蛋的底部,若不能推动则等待15秒再推,重复此过程直至蛋可以推开。这段时间可以加白胡椒粉2调味。
  6. 铲蛋,用筷子夹住边缘并慢慢地翻面
  7. 大概煎40秒,试着用锅铲轻推,如果不行就等待后再推,能推开就可以铲起来吃了。

继续煎蛋的流程 #

  1. 如果粘锅了,洗锅、烧干水,从头开始
  2. 如果没粘锅,铲走残渣后按照第一次的流程煎蛋
  3. 注意现在锅里有油,不要洒水测试温度,水和油混合会炸开,请参考第一次记录的热锅时间进行热锅

窍门 #

  • 蛋下锅那瞬间温度要够高,之后根据你的喜好调节温度和煎的时间
    • 要脆的就用更大档位
    • 要嫩的就用更小档位
    • 要溏心蛋就减少煎的时间
    • 要太阳蛋(单面荷包蛋)就一面煎好后加水稍微覆盖锅底,合盖利用蒸汽煮熟热蛋的上面
  • 粘锅时等待一段时间鸡蛋会放开锅底
  • 多加油更容易成功,熟练后再根据自己的喜好调节油量
  • 鸡蛋也可以用常温的
  • 可以直接打蛋到锅中,但是蛋壳弄进去就没法拿出来了,如果你会铁砂掌也可以拿
  • 测试温度的原理是莱顿弗罗斯特现象,水接触温度远超其沸点的铁锅时,水底部会产生有隔热作用的蒸汽,令水沸腾的速度大大减慢
  • 不粘锅煎蛋更容易成功,但是不要干烧,要先加油再加热
  • 可以每次煎 2 个蛋,但是 3 个就太多了,很难翻面

  1. 我这个电磁炉 500W 时是间隔加热,持续加热的电磁炉应该也是可以的 ↩︎

  2. 胡椒研磨成粉后香味会散发,不推荐用成品胡椒粉,推荐用胡椒加研磨器 ↩︎

Hugo:自定义标签标题

背景 #

一开始我用 Hugo 做中文网站时打算在文章里用中文标签,但是链接里面的中文会被转换为人类读不懂的字符。比如:/zh-cn/tags/博客/ 会变成 /zh-cn/tags/%E5%8D%9A%E5%AE%A2/。我不喜欢这样,当时搜索一番也没找到办法,就用英文标签了。现在终于知道怎么改了,最终改为链接里面还是用英文,但是页面就显示中文。

下面是针对 hugo-theme-jane(ef8a126)主题的更改方法,方法是通用的,但是不同主题修改的部分可能不同。开始前先厘清两个概念:标签名(tag name)、标签标题(tag title)。在文章前页(front matter)写的是标签名,用于链接;在 _index.md 文件定义的是 title 是标签标题,它会显示于页面。

1
2
3
4
5
6
---
# /content/zh-cn/post/2021-03-21-dongman.md
title: 动漫这个词不能再用了
tags:
 - anime # 标签名
---
1
2
3
4
---
# /content/zh-cn/tags/anime/_index.md
title: 日本动画 # 标签标题
---

如果你启用了 GitInfo 而且不想更改 lastmod,请参考 Hugo:给文章添加 lastmod(上次修改时间)

修改标签单页标题(/zh-cn/tags/*/ #

以 anime(日本动画)为例。先自定义一个标签的标题。

1
2
mkdir --parents content/zh-cn/tags/anime/
touch content/zh-cn/tags/anime/_index.md

添加内容:

1
2
3
4
---
# /content/zh-cn/tags/anime/_index.md
title: 日本动画
---

文章前页(front matter)的 tags 还是保持用 anime。

1
2
3
4
5
6
---
# /content/zh-cn/post/2021-03-21-dongman.md
title: 动漫这个词不能再用了
tags:
 - anime
---

现在 /zh-cn/tags/anime/ 会显示「日本动画」。

修改文章底下的标签标题(/zh-cn/post/* #

在浏览器 inspect 找到 CSS 类,然后去 VS Code 搜索。

本地预览网站。随便打开一篇文章(http://localhost:1313/zh-cn/post/2022/12/03/ajin-oad/),滚动到底部的标签,右击 Inspect,可以看到对于的 HTML 代码。

1
2
3
<div class="post-tags">
 <a href="http://localhost:1313/zh-cn/tags/anime/">anime</a>
</div>

搜索主题目录。

1
rg '<div class="post-tags">' themes/jane

可以发现此代码就在 themes/jane/layouts/post/single.html,将其复制到 layouts/post/(我之前复制过,这次跳过此步骤)。

编辑 layouts/post/single.html

找到下面这段代码:

1
2
3
4
5
6
7
8
<div class="post-tags">
 {{ range . }}
 {{- $name := . -}}
 {{- with $.Site.GetPage "taxonomy" (printf "tags/%s" $name) | default ($.Site.GetPage "taxonomy" (printf "tags/%s" ($name | urlize))) -}}
 <a href="{{ .Permalink }}">{{ $name }}</a>
 {{ end -}}
 {{ end }}
</div>

<a href="{{ .Permalink }}">{{ $name }}</a> 里面的 $name 改为 .LinkTitle。改完是这样的:

1
<a href="{{ .Permalink }}">{{ .LinkTitle }}</a>

现在 http://localhost:1313/zh-cn/post/2021/03/21/dongman/ 底下会显示标签「日本动画」。

修改标签列表页面(/zh-cn/tags/ #

用前面的方法 Inspect 元素并搜索代码。

1
rg '<div class="tag-cloud-tags">' themes/jane

可以发现标签列表页面的模板为 themes/jane/layouts/_default/terms.html,复制一份到根目录再改。

1
2
3
4
mkdir --parents layouts/_default/
cp themes/jane/layouts/_default/terms.html layouts/_default/
git add layouts/_default/terms.html
git commit --message 'chore: copy layouts/_default/terms.html'

打开 layouts/_default/terms.html,搜索 tag-cloud-tags,找到这段代码。

1
2
3
4
5
6
<div class="tag-cloud-tags">
...
 <a href="{{ .Permalink }}"
 style="font-size:{{$currentFontSize}}{{$fontUnit}}">{{ $tagName }}</a>
...
</div>

将里面的 $tagName 改为 .LinkTitle

1
2
<a href="{{ .Permalink }}"
 style="font-size:{{$currentFontSize}}{{$fontUnit}}">{{ .LinkTitle }}</a>

提交改动。

1
2
git add layouts/_default/terms.html layouts/post/single.html
git commit --message 'feat: use tag title'

修改所有标签名,加上标签标题 #

标签名全部改成全小写,以连字符分割。改动比较多,新建一个分支,提交完再合并到主分支。

1
git switch --create customize-tag-titles

使用 VS Code 插件 Front Matter CMS 修改标签名。

加标签标题就比较繁琐,要自己创建文件。我让 ChatGPT 给我写了个脚本,好使!

我说的话:

I am customizing tag titles in a Hugo website. I want you to create a CLI program.

1
create-tag-title directory tag-name tag-title

If I run

1
create-tag-title content/en arch-linux 'Arch Linux'

the program should create content/en/tags/arch-linux/_index.md, the content of _index.md should be:

1
2
3
---
title: Arch Linux
---

ChatGPT 给的 Python 脚本(Shebang 是我加的1):

 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
30
31
32
33
34
35
36
37
38
#!/usr/bin/env python 
import os
import sys

def create_tag_title(directory, tag_name, tag_title):
 # Construct the path to the tag directory
 tag_dir = os.path.join(directory, 'tags', tag_name)
 
 # Make the directories if they don't exist
 os.makedirs(tag_dir, exist_ok=True)
 
 # Define the path for the _index.md file
 index_file_path = os.path.join(tag_dir, '_index.md')
 
 # Define the content of the _index.md file
 index_content = f"""---
title: {tag_title}
---
"""
 # Write the content to the _index.md file
 with open(index_file_path, 'w') as index_file:
 index_file.write(index_content)

 print(f"Created {index_file_path} with title: {tag_title}")

if __name__ == '__main__':
 # Ensure the correct number of arguments are provided
 if len(sys.argv) != 4:
 print("Usage: create-tag-title directory tag-name tag-title")
 sys.exit(1)

 # Read the arguments from the command line
 directory = sys.argv[1]
 tag_name = sys.argv[2]
 tag_title = sys.argv[3]

 # Call the function to create the tag title file
 create_tag_title(directory, tag_name, tag_title)

自己写提交信息还是太繁琐,让 ChatGPT 把这部分也加上。

我说的话:

Besides creating the _index.md, I want to stage content/ directory and commit. Example:

1
git add content/; git commit -m 'tag-title: arch-linux -> Arch Linux'

ChatGPT 返回的代码(Shellbang 是我加的):

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python
import os
import sys
import subprocess

def create_tag_title(directory, tag_name, tag_title):
 # Construct the path to the tag directory
 tag_dir = os.path.join(directory, 'tags', tag_name)
 
 # Make the directories if they don't exist
 os.makedirs(tag_dir, exist_ok=True)
 
 # Define the path for the _index.md file
 index_file_path = os.path.join(tag_dir, '_index.md')
 
 # Define the content of the _index.md file
 index_content = f"""---
title: {tag_title}
---
"""
 # Write the content to the _index.md file
 with open(index_file_path, 'w') as index_file:
 index_file.write(index_content)

 print(f"Created {index_file_path} with title: {tag_title}")

 # Stage the content directory
 try:
 subprocess.run(['git', 'add', directory], check=True)
 print(f"Staged {directory}")

 # Commit the changes
 commit_message = f'tag-title: {tag_name} -> {tag_title}'
 subprocess.run(['git', 'commit', '-m', commit_message], check=True)
 print(f"Committed with message: '{commit_message}'")
 except subprocess.CalledProcessError as e:
 print(f"Error during git operation: {e}")

if __name__ == '__main__':
 # Ensure the correct number of arguments are provided
 if len(sys.argv) != 4:
 print("Usage: create-tag-title directory tag-name tag-title")
 sys.exit(1)

 # Read the arguments from the command line
 directory = sys.argv[1]
 tag_name = sys.argv[2]
 tag_title = sys.argv[3]

 # Call the function to create the tag title file
 create_tag_title(directory, tag_name, tag_title)

我使用的 Python 版本是 3.12.4。

检查链接变化 #

可以在修改前后构建网站,用于对比。如果链接有变化,需要重定向旧链接。改了一堆东西,我已经没心思检查了,忽略此步骤。

参考资料 #


  1. 写完文章我才想到可以让 ChatGPT 加 Shebang ↩︎

Hugo:补全文章的 ISO 8601 日期

背景 #

本网站使用 Hugo 构建,文章日期(date)是这样的:

1
date: '2020-10-02'

这里缺少了时间和时区。于是我给全部文章都设置了同一个时区(时间没填就是 00:00:00),但这个办法有隐患。如果我在另一个时区写文章,这时新的文章还是使用了旧时区。所以最好在每篇文章写上日期、时间和时区。

Hugo 日期的格式为 ISO 8601,示例:

1
date: 2020-10-02T00:00:00+08:00

补全日期的方法就是去掉引号1、补上 T00:00:00+08:00T00:00:00 是时间,+08:00是时区。

修改日期前先给全部文章加上 lastmod(上次修改时间),不然修改日期后 lastmod 全部变成今天了。

操作流程 #

在根目录新建 use-iso8601-date.sh,添加执行权限。

1
2
touch use-iso8601-date.sh
chmod +x use-iso8601-date.sh

use-iso8601-date.sh 填入脚本内容。

1
2
3
4
5
6
7
8
#!/usr/bin/env bash
# usage: ./use-iso8601-date.sh directory-name
directory="$1"
files=$(find "$directory" -type f)
for file in $files; do
 sed -i "s|date: '\(.*\)'|date: \1T00:00:00+08:00|g" "$file"
 sed -i 's|date: "\(.*\)"|date: \1T00:00:00+08:00|g' "$file"
done

修改前先构建网站,后面用于对比。

1
2
3
rm --recursive public/
hugo
mv public public-original

补全日期。

1
./use-iso8601-date.sh content

删除时区配置。

1
2
3
4
# config.toml

# 删掉下面这行
timeZone = "Etc/GMT-8"

再次构建网站。

1
2
hugo
mv public public-changed

使用文件对比工具(我用的是 Kompare)对比 public-originalpublic-changed,有一处差异:/en/post/2023/11/06/hugo-top-level-404/ 文内代码块的日期也被修改了。这样改也没错。

预览,稍微和 https://cyrusyip.org/ 对比一下,看起来一样。

1
hugo server

删除构建的网站。

1
rm --recursive public public-original public-changed

查看差异后提交改动。

1
2
3
git diff
git add --update
git commit --message 'feat: use ISO 8601 date'

删除脚本。

1
rm use-iso8601-date.sh

  1. 日期的引号去不去都行,我觉得不用更简洁就选择去掉。 ↩︎

Hugo:给文章添加 lastmod(上次修改时间)

背景:本站文章的 lastmod(上次修改时间)就是 Git 提交的 author date(作者日期)。我需要批量修改文章(Hugo:补全文章的 ISO 8601 日期),这会导致所有文章的 lastmod 都变成今天。文章内容没变就不应该改 lastmod,所以我打算给每篇文章都加上 lastmod,后面改动文章就 lastmod 就不会变。


先把 lastmod 的优先级调至最高,不然 Hugo 会继续使用 Git 提交日期。

1
2
3
# config.toml
[frontmatter]
 lastmod = ['lastmod', ':default']

在根目录新建 add-lastmod.sh,添加执行权限

1
2
touch add-lastmod.sh
chmod +x add-lastmod.sh

add-lastmod.sh 填入脚本内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/env bash
# usage: ./add-lastmod.sh directory-name
directory="$1"
files=$(find "$directory" -type f)
for file in $files; do
 echo "${file}"
 lastmod_date=$(git log --no-show-signature -1 --format=%aI "$file") # example: 2024-05-16T14:23:53+08:00
 echo "$lastmod_date"
 # Use awk to insert the lastmod line above the second ---
 awk -v lastmod="lastmod: $lastmod_date # remove this line if the content is actually changed" '
 BEGIN { frontmatter = 0 }
 /^---$/ { frontmatter++ }
 frontmatter == 2 && !printed { print lastmod; printed = 1 }
 { print }
 ' "$file" >tmpfile && mv tmpfile "$file"
done

修改前先构建网站,后面用于对比。

1
2
3
rm --recursive public/
hugo
mv public public-original

添加 lastmod。

1
./add-lastmod.sh content

再次构建网站。

1
2
hugo
mv public public-changed

使用文件对比工具(我用的是 Kompare)对比 public-originalpublic-changed,结果完全相同。

预览,稍微和 https://cyrusyip.org/ 对比一下,看起来一样。

1
hugo server

删除构建的网站。

1
rm --recursive public public-original public-changed

查看差异后提交改动。

1
2
3
git diff
git add --update
git commit --message 'chore: add lastmod before changing date'

删除脚本。

1
rm add-lastmod.sh

拒绝烂词

迷因图:简单点,说话的方式简单点

最近发现自己越来越讨厌网络词语了,但是一直没细想原因,今天决定仔细思考一下。

我讨厌的词语有(次级列表表示讨厌原因):

  • yyds -> yong yuan de shen -> 永远的神 (形容杰出的人)
    • yyds 是拼音缩写,增加了理解难度。
  • IP -> intellectual property -> 知识产权(可能指「跨媒体制作」或者「网络红人」)
    • IP 是缩写,增加了理解难度;「跨媒体制作」意思清晰,没必要发明新词;「intellectual property」意思增加了,容易造成歧义。
  • city walk(在城市散步)
    • 中文已有「散步」,没必要发明 city walk。
  • 走心(原指「变心」或者「走神」。现在网上有「用心」、「动心」的意思,贬义转褒义了)
    • 中文已有「用心」、「动心」,没必要发明新词;「走心」的意思增加了,容易造成歧义。
  • 百元机(1000元人民币以下的手机)
    • 百元机(1000元以下的手机)不符合直觉,百元机按直觉应该是一百元能买到的手机。
  • 千元机(1000元~2000元人民币的手机)
    • 千元机(1000元~2000元人民币的手机)同样是不符合直觉。
  • emo(引申自 emotion,可以指一切负面情绪,比如:颓废、忧郁、悲伤)
    • emo 意思模糊,你到底是哪种情绪呢?
迷因图:你要不要聽聽看 你現在到底在講什麼

这些词语的问题就是:晦涩难懂、不必要地创造新词、重新定义词语导致歧义、不符合直觉、意义模糊。语言的目的就是传递信息,而费解的词语会阻碍这个过程。我写博客时越来越追求文章通俗简洁,所以就很讨厌这些词语。看来我不是讨厌网络词语,是讨厌烂词。

世界在变化,我们需要创造新词来描述新事物。近年也有一些我觉得不错的网络词语:

  • 全职儿女(一种职业,在家通过做家务等劳动换取父母支付的薪水。)
  • 躺平(很形象地表达不想努力。)
  • 打工人(突出上班就是给别人干活,有自嘲意味。)

前面批评了烂词,我也顺便从中总结我对语言的态度:

  • 保持准确
  • 保持通俗,使更多人理解
  • 继续使用原有词语,能继续用就不需要发明新词
  • 修正费解的词语。比如:鲁棒性(robustness)应该是健壮性;自行车(bicycle)不会自行移动,应该说脚踏车或者双轮车。
  • 可以从外语引入缺乏的词语。比如:咖啡(coffee)、电话(日语借词)。

最后,推荐我自己的中文训练方法:

  • 看到网络词语就在心中翻译
  • 看到中英夹杂就想怎么用纯中文表达
  • 用通俗的词语代替网络词语
  • 表达时考虑受众的知识水平

本文图片出处:

跳过 Android 应用广告

GKD 是开源的屏幕点击应用,可以自动跳过应用的开屏广告和应用内广告。实际测试 GKD 可以跳过铁路 12306 和京东的开屏广告。

使用方法:

  1. 根据官方文档安装并授予权限。
  2. 点击「订阅->右下角加号」,添加规则订阅。

默认规则订阅链接:https://fastly.jsdelivr.net/npm/@gkd-kit/subscription。默认规则于 2024 年 2 月 1日 停止更新,如果失效了可以试试第三方规则或者自己编写规则。GKD 不能跳过所有应用广告,得有对应的规则才行。

KDE Plasma X11 黑屏后重建账号

最近 Arch Linux 升级重启后进 KDE Plasma X11 就黑屏剩下光标,某次升级后 Wayland 也用不上了。在 Arch 论坛看到一个相似的情况,但是里面的方法在我这边没用。提问和等待也要花时间,索性就新建账号吧,至少新账户用 KDE Plasma 没问题。

新建用户 #

按下 Ctrl Alt F4 进入 tty 新建用户。

1
2
useradd --create-home --groups wheel --shell /bin/bash cyrus2
passwd cyrus2

Ctrl Alt F1(也可能是 F2 或者 F3) 返回 sddm 登录新账户。

配置 #

  1. 软件基本都是装在系统,无需重装。
  2. 连接 WIFI
  3. 安装配置文件
  4. 安装 zinit: bash -c "$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/zdharma-continuum/zinit/HEAD/scripts/install.sh)"
  5. 设置默认 Shell:chsh --shell /usr/bin/zsh
  6. 安装 kio-admin,这样 dolphin 才能用管理员权限访问旧账户的家目录
  7. 从旧账号复制配置文件
    • ~/.ssh
    • ~/.gnupg
    • ~/.local/share/keyrings/ (seahorse)
  8. 移动家目录的文件(用 dolphin 复制容易卡住,还时不时询问密码,不要一次弄太多。sudo lf 里面复制的文件权限会变 root。复制 git 仓库超慢,最好忽略。)
    1. Desktop
    2. Documents
    3. Downloads
    4. Music
    5. Pictures
    6. Videos
    7. VirtualBox VMs
  9. 登录软件
    1. 登录 Firefox 和 Brave(Brave 浏览器同步码的最后一个单词每天都不一样
      1. 登录 Bitwarden
    2. 登录 MegaSync 同步文件,同步完后删除旧账户的网盘文件
    3. 登录 Joplin
    4. 登录 VS Code,同步设置
    5. 登录 GitHub CLI
  10. 克隆常用的 Git 仓库
  11. 配置 KDE
    1. 添加 Netspeed Widget
    2. 新建两个 Virtual Desktop
    3. 开机启动(autostart)
      1. MegaSync
      2. Fcitx5
      3. Joplin
    4. bismuth 快捷键设置,Settings -> Shortcuts -> Shortcuts -> Window Tiling,打开需要使用的快捷键
    5. 其他快捷键
      1. Switch to Next Screen = Meta +,
      2. 点击 Window Behavior,关闭 Active screen follows mouse,打开 Separate screen focus
      3. Lock Session = Meta+Ctrl+Space
    6. 特效
      1. Desktop Effects -> Virtual Desktop Switching Animation -> Fade Desktop
    7. 设置 plasma-hud 快捷键
      1
      2
      3
      
      cp ~/.config/kwinrc{,.bak} # 备份
      kwriteconfig5 --file ~/.config/kwinrc --group ModifierOnlyShortcuts --key Alt "com.github.zren.PlasmaHUD,/PlasmaHUD,com.github.zren.PlasmaHUD,toggleHUD"
      qdbus org.kde.KWin /KWin reconfigure
      
  12. GoldenDict 导入词典
  13. 清理旧家目录里不需要的文件,比如 ~/.cache

使用默认配置的感想 #

KDE Plasma 默认单击打开文件,这还挺好用的。

❌