@chengzhao-dev/dsh-quarto-book 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/package.json +5 -2
- package/skills/designing-theme/SKILL.md +2 -2
- package/skills/designing-theme/assets/theme/css/base.css +216 -55
- package/skills/designing-theme/assets/theme/css/callouts.css +32 -23
- package/skills/designing-theme/assets/theme/css/code.css +84 -2
- package/skills/designing-theme/assets/theme/css/content.css +152 -36
- package/skills/designing-theme/assets/theme/css/landing.css +150 -52
- package/skills/designing-theme/assets/theme/css/nav.css +462 -35
- package/skills/designing-theme/assets/theme/css/sidebar.css +76 -31
- package/skills/designing-theme/assets/theme/css/tokens.css +34 -16
- package/skills/designing-theme/assets/theme/includes/fonts.html +1 -1
- package/skills/designing-theme/assets/theme/includes/footer.html +16 -7
- package/skills/designing-theme/assets/theme/includes/palette.html +420 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/brand-mark.svg +3 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/favicon-dark.svg +5 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/favicon-light.svg +5 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/highlight-dark.theme +214 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/highlight-light.theme +214 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/meta.md +53 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/theme-dark.scss +43 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/theme-light.scss +40 -0
- package/skills/designing-theme/assets/theme/palettes/flexoki/tokens.css +156 -0
- package/skills/designing-theme/assets/theme/palettes/hill-light/brand-mark.svg +3 -0
- package/skills/designing-theme/assets/theme/palettes/hill-light/favicon-dark.svg +5 -0
- package/skills/designing-theme/assets/theme/palettes/hill-light/favicon-light.svg +5 -0
- package/skills/designing-theme/assets/theme/palettes/hill-light/meta.md +78 -0
- package/skills/designing-theme/assets/theme/palettes/hill-light/syntax.css +150 -0
- package/skills/designing-theme/assets/theme/palettes/hill-light/tokens.css +322 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/brand-mark.svg +3 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/favicon-dark.svg +5 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/favicon-light.svg +5 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/highlight-dark.theme +214 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/highlight-light.theme +214 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/meta.md +66 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/syntax.css +67 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/theme-dark.scss +43 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/theme-light.scss +41 -0
- package/skills/designing-theme/assets/theme/palettes/solarized/tokens.css +154 -0
- package/skills/designing-theme/knowledge/reading-surface.md +27 -15
- package/skills/designing-theme/references/theme-spine.md +2 -2
- package/skills/designing-theme/references/theme-system.md +82 -36
- package/skills/designing-theme/scripts/checking-layout.py +306 -48
- package/skills/designing-theme/scripts/measuring-pages.mjs +40 -3
- package/skills/writing-quarto/quarto/render.md +2 -2
- package/skills/writing-quarto/scripts/checking-dom.py +14 -7
- package/skills/designing-theme/assets/theme/assets/brand-mark.svg +0 -4
- package/skills/designing-theme/assets/theme/assets/favicon.svg +0 -9
- package/skills/designing-theme/assets/theme/palettes/github/highlight-dark.theme +0 -213
- package/skills/designing-theme/assets/theme/palettes/github/highlight-light.theme +0 -213
- package/skills/designing-theme/assets/theme/palettes/github/meta.md +0 -38
- package/skills/designing-theme/assets/theme/palettes/github/theme-dark.scss +0 -35
- package/skills/designing-theme/assets/theme/palettes/github/theme-light.scss +0 -34
- package/skills/designing-theme/assets/theme/palettes/github/tokens.css +0 -160
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
Palette: solarized · Solarized Light / Dark 运行时覆盖层
|
|
3
|
+
只在 html[data-palette="solarized"] 下生效;默认 Flexoki 不受影响。
|
|
4
|
+
官方页面色:亮底 base3 #FDF6E3、暗底 base03 #002B36。
|
|
5
|
+
链接按官方 rebase:亮 base01 #586E75、暗 base1 #93A1A1;
|
|
6
|
+
蓝色只作 focus / 下划线 hover 的 accent,不涂正文链接。
|
|
7
|
+
阅读文字保持 4.5:1;页面底色与强调色保持官方值。
|
|
8
|
+
============================================================ */
|
|
9
|
+
|
|
10
|
+
html[data-palette="solarized"] body {
|
|
11
|
+
/* Solarized Light 页面令牌 */
|
|
12
|
+
--body-color: #526C74;
|
|
13
|
+
/* 正文强调(strong):base01,比正文深一档 */
|
|
14
|
+
--emphasis-color: #586E75;
|
|
15
|
+
--code-bg: #EEE8D5;
|
|
16
|
+
--code-border: #93A1A1;
|
|
17
|
+
--code-fg: #526C74;
|
|
18
|
+
--code-title-bg: #E7E0CB;
|
|
19
|
+
--code-title-fg: #4C6166;
|
|
20
|
+
--line-num-color: #556C73;
|
|
21
|
+
--inline-code-bg: rgba(82, 108, 116, 0.10);
|
|
22
|
+
--inline-code-fg: #526C74;
|
|
23
|
+
--text-secondary: #586E75;
|
|
24
|
+
/* 官方 rebase:链接取 base01,不取蓝色;hover 才加深并用蓝下划线。 */
|
|
25
|
+
--link-color: #586E75;
|
|
26
|
+
--link-hover-color: var(--action-color);
|
|
27
|
+
--link-underline: rgba(88, 110, 117, 0.45);
|
|
28
|
+
--text-link: var(--link-color);
|
|
29
|
+
--text-underline: var(--link-underline);
|
|
30
|
+
--action-color: #268BD2;
|
|
31
|
+
--table-border: #93A1A1;
|
|
32
|
+
/* callout:编辑注,无填充;note 取 base01,warning 取官方 orange。 */
|
|
33
|
+
--callout-note-border: #586E75;
|
|
34
|
+
--callout-note-bg: transparent;
|
|
35
|
+
--callout-tip-border: #859900;
|
|
36
|
+
--callout-tip-bg: transparent;
|
|
37
|
+
--callout-warning-border: #CB4B16;
|
|
38
|
+
--callout-warning-bg: transparent;
|
|
39
|
+
--callout-important-border: #6C71C4;
|
|
40
|
+
--callout-important-bg: transparent;
|
|
41
|
+
--callout-caution-border: #DC322F;
|
|
42
|
+
--callout-caution-bg: transparent;
|
|
43
|
+
--copy-btn-bg: #FDF6E3;
|
|
44
|
+
--copy-btn-border: #93A1A1;
|
|
45
|
+
--scrollbar-thumb: #93A1A1;
|
|
46
|
+
--selection-bg: rgba(38, 139, 210, 0.20);
|
|
47
|
+
--mark-bg: rgba(181, 137, 0, 0.35);
|
|
48
|
+
--sidebar-hover-bg: rgba(101, 123, 131, 0.08);
|
|
49
|
+
--sidebar-active-bg: rgba(38, 139, 210, 0.10);
|
|
50
|
+
--sidebar-fg: #586E75;
|
|
51
|
+
--accent: var(--action-color);
|
|
52
|
+
--navbar-bg: #FDF6E3;
|
|
53
|
+
--navbar-fg: #526C74;
|
|
54
|
+
--navbar-muted: #586E75;
|
|
55
|
+
--navbar-border: #93A1A1;
|
|
56
|
+
--navbar-input-bg: #EEE8D5;
|
|
57
|
+
--navbar-hover-bg: rgba(101, 123, 131, 0.08);
|
|
58
|
+
--navbar-secondary-bg: rgba(253, 246, 227, 0.88);
|
|
59
|
+
--dot-accent: #268BD2;
|
|
60
|
+
--card-bg: transparent;
|
|
61
|
+
--card-border: #93A1A1;
|
|
62
|
+
--overlay-scrim: rgba(0, 38, 54, 0.44);
|
|
63
|
+
--toc-active: var(--body-color);
|
|
64
|
+
--page-bg: #FDF6E3;
|
|
65
|
+
--surface-raised: #EEE8D5;
|
|
66
|
+
--sidebar-bg: transparent;
|
|
67
|
+
--line-num-bg: rgba(88, 110, 117, 0.06);
|
|
68
|
+
--line-hover-bg: rgba(38, 139, 210, 0.07);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
html[data-palette="solarized"] body.quarto-dark {
|
|
72
|
+
/* Solarized Dark 页面令牌 */
|
|
73
|
+
--body-color: #839496;
|
|
74
|
+
--emphasis-color: #93A1A1;
|
|
75
|
+
--code-bg: #073642;
|
|
76
|
+
--code-border: #586E75;
|
|
77
|
+
--code-fg: #93A1A1;
|
|
78
|
+
--code-title-bg: #0A3F4C;
|
|
79
|
+
--code-title-fg: #A9B7B7;
|
|
80
|
+
--line-num-color: #93A1A1;
|
|
81
|
+
--inline-code-bg: rgba(147, 161, 161, 0.10);
|
|
82
|
+
--inline-code-fg: #93A1A1;
|
|
83
|
+
--text-secondary: #93A1A1;
|
|
84
|
+
/* 官方 rebase:暗色链接取 base1。 */
|
|
85
|
+
--link-color: #93A1A1;
|
|
86
|
+
--link-hover-color: var(--action-color);
|
|
87
|
+
--link-underline: rgba(147, 161, 161, 0.45);
|
|
88
|
+
--text-link: var(--link-color);
|
|
89
|
+
--text-underline: var(--link-underline);
|
|
90
|
+
--action-color: #51A0D5;
|
|
91
|
+
--table-border: #586E75;
|
|
92
|
+
--callout-note-border: #93A1A1;
|
|
93
|
+
--callout-note-bg: transparent;
|
|
94
|
+
--callout-tip-border: #859900;
|
|
95
|
+
--callout-tip-bg: transparent;
|
|
96
|
+
--callout-warning-border: #CB4B16;
|
|
97
|
+
--callout-warning-bg: transparent;
|
|
98
|
+
--callout-important-border: #6C71C4;
|
|
99
|
+
--callout-important-bg: transparent;
|
|
100
|
+
--callout-caution-border: #DC322F;
|
|
101
|
+
--callout-caution-bg: transparent;
|
|
102
|
+
--copy-btn-bg: #073642;
|
|
103
|
+
--copy-btn-border: rgba(147, 161, 161, 0.45);
|
|
104
|
+
--scrollbar-thumb: #586E75;
|
|
105
|
+
--selection-bg: rgba(38, 139, 210, 0.30);
|
|
106
|
+
--mark-bg: rgba(181, 137, 0, 0.30);
|
|
107
|
+
--sidebar-hover-bg: rgba(147, 161, 161, 0.07);
|
|
108
|
+
--sidebar-active-bg: rgba(38, 139, 210, 0.16);
|
|
109
|
+
--sidebar-fg: #93A1A1;
|
|
110
|
+
--accent: var(--action-color);
|
|
111
|
+
--navbar-bg: #002B36;
|
|
112
|
+
--navbar-fg: #839496;
|
|
113
|
+
--navbar-muted: #93A1A1;
|
|
114
|
+
--navbar-border: #073642;
|
|
115
|
+
--navbar-input-bg: #073642;
|
|
116
|
+
--navbar-hover-bg: rgba(147, 161, 161, 0.07);
|
|
117
|
+
--navbar-secondary-bg: rgba(0, 43, 54, 0.90);
|
|
118
|
+
--dot-accent: #51A0D5;
|
|
119
|
+
--card-bg: transparent;
|
|
120
|
+
--card-border: #586E75;
|
|
121
|
+
--overlay-scrim: rgba(0, 0, 0, 0.62);
|
|
122
|
+
--toc-active: var(--body-color);
|
|
123
|
+
--page-bg: #002B36;
|
|
124
|
+
--surface-raised: #073642;
|
|
125
|
+
--sidebar-bg: transparent;
|
|
126
|
+
--line-num-bg: rgba(147, 161, 161, 0.06);
|
|
127
|
+
--line-hover-bg: rgba(38, 139, 210, 0.12);
|
|
128
|
+
color-scheme: dark;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@media (prefers-contrast: more) {
|
|
132
|
+
html[data-palette="solarized"] body {
|
|
133
|
+
--body-color: #405B63;
|
|
134
|
+
--code-fg: #405B63;
|
|
135
|
+
--inline-code-fg: #405B63;
|
|
136
|
+
--navbar-fg: #405B63;
|
|
137
|
+
--link-color: #405B63;
|
|
138
|
+
--emphasis-color: #073642;
|
|
139
|
+
--code-border: #586E75;
|
|
140
|
+
--card-border: #586E75;
|
|
141
|
+
--navbar-border: #586E75;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
html[data-palette="solarized"] body.quarto-dark {
|
|
145
|
+
--body-color: #93A1A1;
|
|
146
|
+
--code-fg: #93A1A1;
|
|
147
|
+
--inline-code-fg: #93A1A1;
|
|
148
|
+
--link-color: #93A1A1;
|
|
149
|
+
--emphasis-color: #EEE8D5;
|
|
150
|
+
--code-border: #93A1A1;
|
|
151
|
+
--card-border: #93A1A1;
|
|
152
|
+
--navbar-border: #93A1A1;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -6,7 +6,7 @@ tags: [fonts, typography, layout, theme, readability, contrast]
|
|
|
6
6
|
level_range: [0, 5]
|
|
7
7
|
dependencies: []
|
|
8
8
|
created: "2026-10-10"
|
|
9
|
-
updated: "2026-10-
|
|
9
|
+
updated: "2026-10-22"
|
|
10
10
|
chunk_strategy: "semantic_heading"
|
|
11
11
|
estimated_tokens: 1500
|
|
12
12
|
---
|
|
@@ -15,9 +15,15 @@ estimated_tokens: 1500
|
|
|
15
15
|
|
|
16
16
|
本文件回答这本书的阅读表面为什么这样定:正文字体、正文栏宽、窄屏行为与加粗/链接颜色。怎么做(改哪一步、动哪个文件)见 `designing-theme` 技能的 `references/theme-spine.md`,数值与实现见 `references/theme-system.md`。本文件只放理由。这套主题由本插件维护,不与其他仓库共享;项目若复制了资产,以项目 `_quarto.yml` 实际引用的副本为准。
|
|
17
17
|
|
|
18
|
-
## 正文为什么是 LXGW
|
|
18
|
+
## 正文为什么是 LXGW,标题为什么用系统无衬线
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
正文保持霞鹜文楷路线(楷体):这本书是长时间连续阅读的技术书,楷体的笔画变化比几何无衬线更耐读;作者「文楷不适合超长正文」的评价针对的是屏幕上偏细的 Regular,不构成换字体的理由——用 Bright 的 Medium 解决偏细。
|
|
21
|
+
|
|
22
|
+
标题与导航改用系统无衬线栈(Noto Sans SC / PingFang SC / 微软雅黑),形成「黑体标题 + 楷体正文」的双字面。单一文楷时层级只能靠字号,H2/H3 与正文同面,章节入口不够清楚;标题都很短,不需要长文楷体的耐读性,无衬线的 600 字重和字面差能把层级拉开。正文不换黑体,长文仍由楷体承担。
|
|
23
|
+
|
|
24
|
+
### 为什么用系统字体栈,而不是新增字体文件
|
|
25
|
+
|
|
26
|
+
Noto Sans SC、PingFang SC、微软雅黑在主流桌面已经安装;系统栈不必再分发 17MB 的 CJK 字体,也守住「主题不新增字体文件」的约束。Windows 落到 Noto Sans SC,macOS 落到 PingFang SC,Linux 落到 Noto Sans CJK;缺少这些字体时回退到系统 sans,不落回正文楷体。字体文件仍只有 LXGW Bright Medium 与 Bright Code 两份。
|
|
21
27
|
|
|
22
28
|
### 为什么合并成一份 Bright Medium
|
|
23
29
|
|
|
@@ -29,19 +35,23 @@ estimated_tokens: 1500
|
|
|
29
35
|
|
|
30
36
|
### 代码西文与正文西文为什么不是同一个设计
|
|
31
37
|
|
|
32
|
-
代码块的西文是 Monaspace Argon,正文西文是 Ysabeau,两者不是一套——这是配对理由,不是待修缺陷:文楷等宽配别的西文时楷体与西文不协调,Argon 是上游作者认为与楷体风格最接近的等宽字,西文经收窄再缩至 90%,与汉字 advance 成 1∶2,代码列按 1∶2 对齐。字重表有意错位:Bright Code 的 Regular 对应文楷 Medium;主题子集已用 fontTools 读 name 表核对为 LXGW Bright Code Regular(OS/2 weight 400
|
|
38
|
+
代码块的西文是 Monaspace Argon,正文西文是 Ysabeau,两者不是一套——这是配对理由,不是待修缺陷:文楷等宽配别的西文时楷体与西文不协调,Argon 是上游作者认为与楷体风格最接近的等宽字,西文经收窄再缩至 90%,与汉字 advance 成 1∶2,代码列按 1∶2 对齐。字重表有意错位:Bright Code 的 Regular 对应文楷 Medium;主题子集已用 fontTools 读 name 表核对为 LXGW Bright Code Regular(OS/2 weight 400),代码里的汉字笔画与正文同一档,不是「代码更细」。因此不因「代码西文与正文西文不同源」换字体,也不为对齐西文改用黑体路线的等宽字。字体配对调研曾建议换成 Maple Mono CN / Sarasa Term(连字与 OpenType 特性更全),但本书代码示例以棋盘与算法为主,用不到连字,Bright Code 的 1∶2 对齐与楷体笔画与正文同风格,换字体会让代码块的汉字笔画与正文脱节,故保持 Bright Code 不变;子集文件 641KB 也在 1.6MB 预算内。
|
|
39
|
+
|
|
40
|
+
### 数学轴上的 `+ - = × ÷` 为什么不抬到汉字中线
|
|
41
|
+
|
|
42
|
+
`++`、`+=`、`a + b` 里看起来「偏下」不是缺字:fontTools 读两份 woff2 的 cmap,`+ - = < > / * : ; ( ) [ ] { } ~ #` 码位全在子集里;墨迹框量出 `+ = × ÷` 的中心都在基线上方 `0.23em`,汉字「中」在 `0.357em`。差距来自字体把运算符放在数学轴上(x-height 的一半),而等宽代码里 `++c` 的 `c` 中心同样在 `0.23em`,`++` 与它齐平;`C`、`x` 的目测位置也按这条轴读。只把 `++` 下移会脱离同行的 `=`、`÷`、`<`、`<<`(代码里它们成组出现),所以 `.plus-align` 一类逐符号位移不采用,也不为对齐汉字中线改 `translateY`。同理 `<` `>` 在正文同样落在数学轴上、不偏高,章节翻页箭头就直接用这两个字符(`css/sidebar.css` 的 `.nav-page-previous/.nav-page-next` 伪元素),不用 SVG:换 chevron 反而要为它另配一套基线,且和正文里的 `<` `>` 不在同一条轴上。
|
|
33
43
|
|
|
34
44
|
### 排除的候选
|
|
35
45
|
|
|
36
|
-
Inter
|
|
46
|
+
Inter 不采用:正文与标题已经由文楷和系统无衬线分工,不引入第三套西文。思源黑体只以系统 Noto Sans SC 的身份用于标题/界面,不作为正文字面;正文仍是楷体。JetBrains Mono、Cascadia、Iosevka、Inconsolata 是代码字体(代码已有 Bright Code)。Roboto 与 Segoe UI 是 Apache/微软许可,不满足本书「只收 OFL 到 `assets/theme/assets/fonts/`」的政策;系统栈只调用已安装字体,不复制文件。旧式数字(Ysabeau Infant 一系)不适合和汉字混排,不用于这本书。
|
|
37
47
|
|
|
38
48
|
## 栏宽为什么是 872px(内容列 840px)
|
|
39
49
|
|
|
40
|
-
Bright Code 在 16px 下每个 ASCII 字符前进 8px
|
|
50
|
+
Bright Code 在 16px 下每个 ASCII 字符前进 8px;现在代码正文 15px(每字符约 7.5px),100 列加左右内边距与边框约 782px。Quarto 会从 `body-width` 中再减去两侧各 1rem 的栅格内边距(内容列 = body-width − 32px),`body-width` 仍取 872px、内容列 840px,给 16px 代码与行号留余量;不因代码缩到 15px 收窄正文。栏宽随代码列宽走而不是随显示器走:宽视口只增大外侧留白,正文行长保持在可读范围(WCAG 建议不超过约 80 个拉丁字母或 40 个汉字)。标题下的 description 副标题与正文段落同一内容列,不再用 `ch` 二次限宽(Bright 的西文是比例字体,`ch` 只量出半个汉字宽,会先于正文折行)。
|
|
41
51
|
|
|
42
52
|
## 正文间距为什么收成四档
|
|
43
53
|
|
|
44
|
-
全站块间距只有四档:粘连 0.5rem、相关 1rem、换段 1.
|
|
54
|
+
全站块间距只有四档:粘连 0.5rem、相关 1rem、换段 1.4rem、换节 3.25rem(h3/h4/h5 前 2.25rem)。档位按「两块内容是不是同一件事」取:标题与它的首段、caption 与它描述的代码块是粘连;代码块与紧随的说明、callout 与上下文是相关;换一段是换段;换一节是换节。旧表里 1.375rem、1.55rem、0.625rem、0.75rem 这类只差 0.1rem 上下的值收进最近档:读者对 0.1rem 级差异不敏感,维护者却要为每个一次性值另想理由,间距表从此不再增长。h2 的 `margin-bottom` 与相邻 margin-top 折叠取大者,所以设 0.5rem 而不是 1rem——否则标题与首段的粘连档会被折叠抬高一倍。首页眉标 0.9rem 与 description 1.8rem 不在四档内:首页 Hero 是引导面不是正文容器,间距由首屏构图决定。
|
|
45
55
|
|
|
46
56
|
## 窄屏为什么只让代码块横向滚动
|
|
47
57
|
|
|
@@ -49,20 +59,22 @@ Bright Code 在 16px 下每个 ASCII 字符前进 8px,代码区内边距左右
|
|
|
49
59
|
|
|
50
60
|
## 加粗为什么仍合成且不用链接色
|
|
51
61
|
|
|
52
|
-
书里的 `**`
|
|
62
|
+
书里的 `**` 大量用作列表小标题(「出错的原因」「正确的做法」)和行内强调;正文的 Bright 只有一个字面,若同时去掉合成加粗和强调色,这些字与正文无差别(标题已改用黑体栈,加粗在标题上由系统字面真正完成;合成加粗只服务正文里的 `strong`)。因此:`strong` 保留 `font-synthesis: weight` 的合成(全站唯一放开点),配一个不取链接色的强调色:Flexoki 亮色与正文同墨色、靠合成字重区分,暗色更亮;Solarized 亮色深一档、暗色更亮。这样加粗必须和链接在明暗两套下都能区分。列表里独占一段的 `**` 小标题保持正文色块级形态,避免一列蓝标题;代码文件名、行内代码、kbd 各用自己令牌,不被强调色或链接色串染。
|
|
53
63
|
|
|
54
64
|
## 颜色与对比度的取值依据
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
编译默认色板是 Flexoki(亮纸 `#FFFCF0`、暗墨 `#100F0F`),Solarized 是读者运行时可选的第二套。两套都只换语义令牌和语法色,不换字体、栏宽与组件。Flexoki 的 callout 是编辑注:2px 左条、无填充、无圆角,note 取中性灰,其余用官方语义色(tip 绿、warning 橙、important 紫、caution 红)。文本对比度按 WCAG 2.2 的 1.4.3(4.5:1)校验:正文、强调、链接、13px 表头、14px 图注与代码标题在各自底色上低于 4.5:1 时升到更实的一档,不改成纯黑或纯白,也不借用语法蓝。链接本身不靠颜色,常态与正文同色并保留下划线;Solarized 的正文与注释抬到 4.5:1,链接回到官方 rebase(base01 / base1),页面底色、强调色与 callout 条保持官方值。
|
|
67
|
+
|
|
68
|
+
第三套是读者自己的「山光」四时色板(`palettes/hill-light`,取自 `D:\Github\hill-light\hill-light-theme` 的单一色值来源):晓雾、午荫、暮烟三种浅纸与夜月一种暗纸。它不是照搬原站,而是过一遍本书的令牌契约:保留原站的色相与命名,按本书的 WCAG 4.5:1 校验抬了正文与表头,callout 类型色与代码语法色沿用本书的语义映射(原站的 callout 与代码几乎是单色)。四种时辰里只有夜月是暗色,所以它同时要驱动 Quarto 的 light/dark 基座——`includes/palette.html` 在首帧写 `quarto-color-scheme` 哨兵,运行时对齐 `body` 类;打印时夜月回落到晓雾令牌,纸面不出深底。
|
|
57
69
|
|
|
58
|
-
##
|
|
70
|
+
## 抬色记录与保留的低对比项
|
|
59
71
|
|
|
60
|
-
|
|
72
|
+
Flexoki 亮色注释从官方 `#6F6E69` 抬到 `#575653`(本书代码底 `#F2F0E5` 上 6.42:1),行号同步;暗色保持官方 `#878580`(`#1C1B1A` 上 4.67:1)。官方文档注释档(亮 `#B7B5AC` / 暗 `#575653`)分别只有 1.8:1 / 2.3:1,未采用。
|
|
61
73
|
|
|
62
|
-
|
|
74
|
+
Solarized 的正文与注释各抬一档:亮色正文/代码字/顶栏字 `#526C74`(纸 5.18:1,代码底 4.56:1)、亮色注释与行号 `#556C73`(代码底 4.54:1);暗色正文 `#839496`(4.75:1)与暗色注释 `#93A1A1`(代码底 4.86:1)本来达标,不动。链接遵循官方 `rebase`:亮 base01 `#586E75`(纸 4.99:1)、暗 base1 `#93A1A1`(暗底 5.61:1),hover 才转官方蓝 `#268BD2` / `#51A0D5`;语法标识符蓝仍用抬过的 `#1B6EA3` / `#51A0D5`。页面底色 base3/base03、强调色 base01 与 callout 左条不改;官方蓝在亮纸 3.41:1、暗底 4.08:1,不作正文链接常态色。完整比值与取色理由见 `palettes/solarized/meta.md`。
|
|
63
75
|
|
|
64
|
-
|
|
76
|
+
## 明暗代码色跟哪一对主题
|
|
65
77
|
|
|
66
|
-
|
|
78
|
+
Flexoki 页面色与语法色同源:`palettes/flexoki/highlight-light.theme` / `highlight-dark.theme` 取自 Flexoki 官方 VS Code 主题的语法映射,`BackgroundColor` 与 `--code-bg` 相同(亮 `#F2F0E5`、暗 `#1C1B1A`),不使用 Quarto 内置的浅色/深色语法主题——那对是 2020 年的 skylighting 主题,按白底与旧深色底设计,叠在 Flexoki 代码底上会错层。
|
|
67
79
|
|
|
68
|
-
|
|
80
|
+
三处允许偏离官方语法映射,其余照抄:亮色注释从官方 `#6F6E69` 抬到 `#575653`(6.42:1);暗色注释保持官方 `#878580`(4.67:1);两套的 Normal 用页面正文色(亮 `#100F0F` / 暗 `#CECDC3`),与 `--code-fg` 一致。Solarized 不参与编译,Quarto 仍输出 Flexoki 的 token class,`palettes/solarized/syntax.css` 在 `html[data-palette="solarized"]` 下覆盖;语法蓝与注释用抬过的 `#1B6EA3` / `#556C73`(亮)与 `#51A0D5` / `#93A1A1`(暗),其余语法色仍官方 accent。Solarized 自己的两套 `.theme` 只作为整本色板编译的素材保留,当前渲染不使用。
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
| 步骤 | 动作与产出 | 登记的文件与一节 |
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| 1 定表面 | 这次动的是正文、代码、Callout 还是导航;只判定,还不动 CSS | 本文件的步骤表 |
|
|
12
|
-
| 2 定字体 |
|
|
12
|
+
| 2 定字体 | 正文中文保持霞鹜楷体路线;标题/导航书名用 `--heading-font` 系统黑体栈(正文内的 `strong` 仍合成加粗);西文和代码按已有决定,产出字体栈改动 | `references/theme-system.md`「字体栈与字形来源(定字体)」+ `assets/theme/css/fonts.css` |
|
|
13
13
|
| 3 定尺度 | 字号台阶、行长与栏宽;视口不够时不改字号,只让代码块横向滚动 | `references/theme-system.md`「字号、行长与页面尺度(定尺度)」+ `assets/theme/css/tokens.css` |
|
|
14
|
-
| 4 定颜色 | 正文、强调、链接、次要文字、代码标题在 `body` 与 `body.quarto-dark`
|
|
14
|
+
| 4 定颜色 | 正文、强调、链接、次要文字、代码标题在 `body` 与 `body.quarto-dark` 各写一套;Solarized 覆盖层写 `html[data-palette="solarized"]`,山光覆盖层写 `html[data-palette="hill-light"][data-mode="…"] body`;代码语法色默认改 `palettes/flexoki/highlight-light.theme` / `highlight-dark.theme` 两份主题文件,Solarized 与山光的语法色写各自 `palettes/<name>/syntax.css`;切换后核对加粗、链接、链接里的加粗、列表小标题和代码文件名没有串色 | `references/theme-system.md`「令牌与色板(定颜色)」+ `assets/theme/palettes/flexoki/tokens.css` + `assets/theme/palettes/flexoki/highlight-*.theme` + `assets/theme/palettes/solarized/syntax.css` |
|
|
15
15
|
| 5 定组件 | 只打开要改的那一个 `assets/theme/css/*.css`;导航字重、答案折叠、行内代码、复制按钮、打印换行属于这一步,不在定颜色里顺手改 | `references/theme-system.md`「组件约定(定组件)」对应条目 |
|
|
16
16
|
| 6 通过检查 | `scripts/checking-layout.py`,然后整本 `render`;只检查,不在这一步发明新的字号或颜色 | `scripts/checking-layout.py`;检查项回到本步骤表与 `theme-system.md`「组件约定」 |
|
|
17
17
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## 令牌与色板(定颜色)
|
|
4
4
|
|
|
5
|
-
令牌语义与流程见本文件。**颜色**只写在 `palettes/<name>/tokens.css
|
|
5
|
+
令牌语义与流程见本文件。**颜色**只写在 `palettes/<name>/tokens.css` 与同目录的品牌标/标签图标(`brand-mark.svg`、`favicon-light.svg`、`favicon-dark.svg`);Solarized 与山光的语法色是仅有的 CSS 例外,写在各自的 `palettes/<name>/syntax.css`。**结构尺度**(字号、半径、字体栈、`--content-width`)写在 `css/tokens.css`。本文件不维护数值副本。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
编译默认色板是 `palettes/flexoki`(Flexoki Light / Dark);`palettes/solarized` 与 `palettes/hill-light`(山光四时:晓雾/午荫/暮烟/夜月)是运行时可选覆盖层,不参与编译。每个色板目录带同一枚「打开的书」品牌标与明暗两份标签图标;书标外形全站一份,颜色随色板。换默认色板时只改 `_quarto.yml` 的 pack SCSS、`palettes/<name>/tokens.css` 与 `highlight-style`,共享组件 CSS 不动。
|
|
8
8
|
|
|
9
9
|
### 令牌索引
|
|
10
10
|
|
|
@@ -13,31 +13,36 @@
|
|
|
13
13
|
| 页面底色 / 浮起面 | `--page-bg` / `--surface-raised` | 页面与抬升表面 |
|
|
14
14
|
| 正文最大宽度 | `--content-width` | 正文容器上限,不是段落二次限宽 |
|
|
15
15
|
| 正文 / 次要文字 | `--body-color` / `--text-secondary` | 正文层级 |
|
|
16
|
-
| 正文强调 / 链接 | `--emphasis-color` / `--link-color` / `--text-link` |
|
|
16
|
+
| 正文强调 / 链接 | `--emphasis-color` / `--link-color` / `--link-hover-color` / `--text-link` | 强调不用链接色;链接常态与正文同色,hover 才用 `--link-hover-color` |
|
|
17
17
|
| 代码外观 | `--code-*` / `--code-title-*` | 语言块、纯文本块与代码标题 |
|
|
18
18
|
| 表格 / 卡片边框 | `--table-border` / `--card-border` | 分隔与边框 |
|
|
19
19
|
| 眉标与状态点 | `--dot-accent` | 首页与状态强调 |
|
|
20
20
|
| 顶栏 | `--navbar-*` | 导航、搜索与主题切换 |
|
|
21
|
+
| 标题字面 | `--heading-font` | h1–h6、导航书名、卡片小标题;系统黑体栈 |
|
|
22
|
+
| 覆盖层遮罩 | `--overlay-scrim` | 搜索浮层、源码模态与窄屏侧栏遮罩 |
|
|
23
|
+
| 圆角 | `--radius-sm` / `-md` / `-lg` | 只有 3 / 4 / 6px 三档;正文与卡片惯用 `--radius-sm`(3px) |
|
|
21
24
|
|
|
22
|
-
### callout 色(左条 +
|
|
25
|
+
### callout 色(左条 + 无填充)
|
|
23
26
|
|
|
24
|
-
每个内置 callout 有一对 `--callout-<type>-border` / `-bg`,写在活跃 palette。SCSS `$callout-*` 须与 border 同步,供编译期图标 data URI
|
|
27
|
+
每个内置 callout 有一对 `--callout-<type>-border` / `-bg`,写在活跃 palette。SCSS `$callout-*` 须与 border 同步,供编译期图标 data URI。条色用当前色板的语义色:Flexoki 的 note 取中性 `#6F6E69` / `#9F9D96`,tip 绿、warning 橙 `#BC5215` / `#DA702C`、important 紫、caution 红,暗用对应 accent-400;Solarized 的 note 取 base01 / base1,warning 用官方 orange `#CB4B16`。`-bg` 一律 `transparent`,callout 是编辑注,不是彩色卡片。
|
|
25
28
|
|
|
26
29
|
### 强调、链接与明暗一致性
|
|
27
30
|
|
|
28
|
-
- 正文 `strong` 用「颜色 + 加粗」双重强调(`content.css`):`font-weight: 700` 加 `font-synthesis: weight`——全站只有 Bright Medium 一个字面且 body 禁合成,合成只放开给 strong
|
|
31
|
+
- 正文 `strong` 用「颜色 + 加粗」双重强调(`content.css`):`font-weight: 700` 加 `font-synthesis: weight`——全站只有 Bright Medium 一个字面且 body 禁合成,合成只放开给 strong;强调色不取语法蓝:Flexoki 亮色与正文同墨色、靠合成字重区分,暗色更亮;Solarized 亮色深一档、暗色更亮。
|
|
29
32
|
- 列表里独占一段的 `strong`(如「出错的原因」)保持块级小标题,颜色用正文色,不走强调色。
|
|
30
33
|
- 链接里的加粗跟链接色走;代码文件名用自己的 `--code-title-fg`,不被 strong 强调色盖住。
|
|
31
34
|
- 行内代码与 `kbd` 保持「弱底 + 正文色」,不继承强调色。
|
|
32
|
-
- `prefers-contrast: more`
|
|
35
|
+
- `prefers-contrast: more` 段只把正文、边框与行号收紧到更深档,不换色相,也不把强调色改成语法蓝。
|
|
33
36
|
- 组件 CSS 不写色值,明暗各写一套;切换后核对加粗、链接、链接里的加粗、列表小标题和代码文件名没有串色。
|
|
34
37
|
|
|
35
38
|
## 字体栈与字形来源(定字体)
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
正文与标题各一面。**正文**用 `LXGW Bright Medium`(Klee One 中笔画 + Ysabeau Office 西文,登记 `font-weight: 400`,`font-synthesis: none` 下不合成粗体);**代码**用 `LXGW Bright Code`(Klee + Monaspace Argon);**标题**(h1–h6、导航书名、首页卡片小标题)用 `--heading-font` 的系统黑体栈(`Noto Sans SC` → 思源黑体 → `PingFang SC` → `Microsoft YaHei` → system-ui),请求 600/700 时由系统字面真正加粗。理由:单字面的楷体在 24px 以上笔画偏细、600 又不合成,标题与正文层级只靠字号,层级弱;对照实测 h2 换黑体后层级立刻清楚,且不新增字体文件、不影响正文观感。中文正文保持霞鹜楷体路线;文楷 Screen 与 Fixel 已移除。候选对比、授权与字面实测(数字等宽、标点宽度、`+` 墨迹 0.23em)见 `docs/research/font-selection.md`。西文来源依据:文楷仓库点名 Ysabeau;Bright 用齐线数字的 Ysabeau Office;文楷 Screen 的 Medium 笔画标 Regular、度量对齐 Roboto,不适合中西文都自托管的站点。
|
|
38
41
|
|
|
39
42
|
- 文件与预算:`assets/theme/assets/fonts/` 每字体一个 `*-common.woff2`(共 2 个),单页合计 ≤ 1.6 MB、≤ 5 个文件。
|
|
40
43
|
- 子集:沿用常用字表并覆盖全书正文与终端输出;生成方式 `pyftsubset --flavor=woff2 --no-hinting`。改结果文案或新增字符后,用 fontTools 读 woff2 cmap 复核(起因:子集共用字符表漏「胜」,结果行末字落到宋体);`checking-layout.py` 的覆盖断言在未声明 unicode-range 时直接读 cmap。
|
|
44
|
+
- 覆盖范围不只汉字:西文标点、数学/箭头、制表符、几何图形与全角形式(U+FF01–FF5E)同在断言内(`GLYPH_RANGES`)。漏一个字不会被发现,却会静默回落到系统 CJK 字体,按 0.5em 的中线画出——正文 `+` 墨迹在 0.23em,「++」会显得浮在汉字上方。表情符号(≥U+1F000、U+2600–U+27BF)按设计走系统 emoji,不在断言内。
|
|
45
|
+
- 不逐符号位移:Bright 的数字、括号、`× ÷ = +` 共用同一条数学轴(+ 中心 0.23em,汉字 0.357em)。只抬 `++` 会脱离同行的符号,所以 `.plus-align` 这类 `translateY` 已删除;对齐问题只在字形缺失时补码位。
|
|
41
46
|
- 同步点:改字体须同步 SCSS、tokens、fonts、OFL、资产与 `checking-layout.py`;Mermaid 的 `%%{init}%%` 与坐标图脚本的 `FONT_FAMILY` 用同栈短版(`LXGW Bright Medium, system-ui, sans-serif`),保证测量与渲染一致。
|
|
42
47
|
- 栈尾 CJK 系统字体兜底(PingFang SC、Microsoft YaHei、Noto Sans CJK SC、Source Han Sans SC)保留,缺字时落系统黑体而不是浏览器默认宋体。
|
|
43
48
|
- 不采用 Inter、思源黑体、JetBrains Mono、Cascadia、Iosevka、Inconsolata;Roboto/Segoe UI 不放进 `assets/theme/assets/fonts/`(OFL 政策)。
|
|
@@ -46,40 +51,64 @@
|
|
|
46
51
|
|
|
47
52
|
| 元素 | 值 |
|
|
48
53
|
|---|---|
|
|
49
|
-
| 正文 |
|
|
54
|
+
| 正文 | 17px(1.0625rem)/ lh 1.85 / 内容列 840px |
|
|
50
55
|
| H1(title) | 32px / w600 |
|
|
51
|
-
| H2 | 24px / w600 / mt
|
|
52
|
-
| H3 |
|
|
56
|
+
| H2 | 24px / w600 / mt 3.25rem mb 0.5rem |
|
|
57
|
+
| H3 | 19px(1.1875rem)/ w600 / mt 2.25rem |
|
|
53
58
|
| H4 | 18px / w600 |
|
|
54
|
-
| 代码块 |
|
|
59
|
+
| 代码块 | 15px(0.9375rem)/ lh 1.7 |
|
|
55
60
|
| 行内代码 | 0.875em |
|
|
56
|
-
| Callout 正文 / 标题 | 16px /
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
| Callout 正文 / 标题 | 16px / 13px |
|
|
62
|
+
| 脚注 / 图注 / 表题 | 14px(0.875rem)/ lh 1.65–1.7 / `--text-secondary` |
|
|
63
|
+
| 表头 | 15px(0.9375rem)/ 正文色 |
|
|
64
|
+
| H6 | 13.6px(0.85rem)|
|
|
65
|
+
|
|
66
|
+
- 层级靠「字号台阶 + 字面分工」:正文只有楷体一面,标题与导航书名用黑体栈,`font-weight: 600` 只在黑体上有视觉意义;正文内的 `strong` 仍走合成加粗(见「强调、链接与明暗一致性」)。
|
|
67
|
+
- 正文 17px / 行高 1.85,代码 15px / 1.7;章节分隔靠 H2 的 `margin-top`,无通栏底线。
|
|
68
|
+
- `grid.body-width` 是正文列上限(现 300+872+272+2×16=1476 封顶);Quarto 会从 body-width 中减去两侧各 1rem 的栅格内边距,正文内容列 = body-width − 32px(现 840px)。取 872px 是让代码块 100 列(15px 下约 782px)与行号仍有富余的最小配置。取值只在 `_quarto.yml`,`--content-width` 只限正文容器;禁止 `75ch` 二次限宽。
|
|
61
69
|
- 代码块不折行:`white-space: pre` + 块内横向滚动(`_quarto.yml` 的 `code-overflow: scroll`);窄视口整页不出横向滚动条,打印时恢复折行(`code.css` 的打印规则)。
|
|
62
70
|
- ≤991.98px 左栏浮层必须不透明实底(规则在 `assets/theme/css/sidebar.css` 的 991.98px 媒体查询)。
|
|
71
|
+
- 栏与栏之间不画竖墙:桌面三栏靠 `#quarto-header` 下一条通栏 1px `--card-border` 分隔,左右两栏在桌面没有 `border-right`(Quarto `sidebar.border` 的竖线被 `#quarto-sidebar.sidebar.sidebar-navigation { border-right: 0 !important }` 压掉);`≤991.98px` 的浮层右缘 1px 是抽屉边,不是栏间墙。
|
|
72
|
+
- 右目录每条的 1px 左轨、当前项 2px `--accent` 色条,以及左栏当前项的左色条都保留:它们标的是「读到哪一节」,不是栏边界。
|
|
63
73
|
|
|
64
74
|
## 组件约定(定组件)
|
|
65
75
|
|
|
66
76
|
- **代码块**:弱底 + 细边。有 `filename` 时用标题条,复制钮右上角;复制钮边框和图标用 `--text-secondary`(暗色下按钮底与代码底同色,边框太暗图标会沉进去)。
|
|
67
|
-
- **Callout
|
|
68
|
-
- **侧栏 active
|
|
69
|
-
- **列表与折叠**:marker 用 `--text-secondary
|
|
70
|
-
-
|
|
71
|
-
-
|
|
77
|
+
- **Callout**:2px 左条、无填充、无圆角;标题 13px、字距 0(汉字等宽,加字距只把词拉散)、正文色;正文 16px;左条 2px、无填充、无圆角;内链接用正文链接色。
|
|
78
|
+
- **侧栏 active**:只保留 `--accent` 左轨与正文色,不加浅底、不加圆角;右目录 active 同策略(正文色 + 色条,`!important` 压住 Quarto 写死的亮蓝,暗色不得漏亮蓝);侧栏与目录焦点环用中性灰,正文焦点环用动作色。
|
|
79
|
+
- **列表与折叠**:marker 用 `--text-secondary`,折叠三角用正文色;答案盒子只用上下 hairline,不做卡片。
|
|
80
|
+
- **首页目录**:不是卡片;每行一条顶线、透明底、无圆角,一行最多两列;单张卡占满整行,序号 `01` 起、动作链接靠右下,窄屏动作移到提要下方;hover 只把顶线换成 `--accent`。
|
|
81
|
+
- **章节翻页**:一条顶线 + 左右两个文字链接,不用边框卡片;箭头用 `<` / `>`,hover 才转 `--accent`,下一页右对齐。箭头用字符而不用 SVG 是量过的:Bright 的 `<` `>` 墨迹中心在 0.23em,与同行西文同一轴,没有面包屑 `>` 那种偏高,换 SVG 反而要另配基线。
|
|
82
|
+
- **章节线**:标题不画线。全书只有一种横线——通栏 1px `--card-border` 发丝线,只出现在顶栏底边、引用块上下边、表格 booktabs、首页目录每行顶线、翻页顶线、页脚顶线、答案折叠线;`h2::after` 的 2.25rem 短发丝线已删除(连同首页 `.feature-grid` 例外),章节节奏只靠 H2 的 `margin-top: 3.25rem` 与字号台阶。契约改动时同步本节与 `css/base.css`。
|
|
83
|
+
- **引用块**:上下各一条 1px `--card-border` 横线、正文色、无底色、无左右竖条;与 Callout 的 2px 左色条区分开(后者是类型标记,不是分隔线)。
|
|
84
|
+
- **表格**:`display: block` + 块内横向滚动承载宽表;Chrome 的表格修复会把同一块里的 `thead`/`tbody` 包进一个匿名表,所以列宽仍逐列对齐(1280 与 390 实测一致),不需要 JS 量列宽。表题走 `caption-side: top`、左对齐、14px `--text-secondary`;`table-striped` 压平成与普通行同底。
|
|
85
|
+
- **脚注**:区块顶部一条 1px `--card-border`、`margin-top: 3rem`、14px / lh 1.7、`--text-secondary`;回跳箭头随正文链接色。
|
|
86
|
+
- **任务列表**:`input[type=checkbox]` 用 `accent-color: var(--action-color)`,不用系统蓝。
|
|
87
|
+
- **图片**:正文图与坐标图圆角一律 `--radius-sm`(3px),不用 6px 大圆角;图注选择器同时覆盖 `figure figcaption`、`.quarto-float-caption`、`.figure-caption`(`lang: zh` 后 Quarto 生成「图 3.1: …」,`lang` 必须写在 `_quarto.yml`,否则图/表题回落英文 Figure/Table)。
|
|
88
|
+
- **图片灯箱**:`format.html.lightbox` 打开后 GLightbox 默认 0.7 黑遮罩,页面图注会从图后透出;主题把遮罩加深到 0.86、关闭/翻页按钮做成 32% 黑的圆钮白描边。透明底 SVG 必须垫白卡(`img[src$=".svg"]`),否则深色遮罩上会整幅消失;位图不加白边。
|
|
89
|
+
- **顶栏品牌标**:`palettes/<name>/brand-mark.svg` 作 `mask`、以 `--navbar-fg` 上色;外形是同一枚「打开的书」,16px 仍可辨。标签页用同目录 `favicon-light.svg` / `favicon-dark.svg`,`book.favicon` 指 Flexoki light,其余五份随 `resources` 发布,`palette.html` 按色板与明暗换 href。图标高 1.25rem、与标题间距 0.5rem,`margin-bottom: 0.2rem` 对齐汉字基线;窄屏先压搜索再省标题。
|
|
90
|
+
- **顶栏搜索**:Quarto 的 Algolia detached button 自带 `svg.aa-SubmitIcon`,主题不再给 `#quarto-search` 画伪元素放大镜;按钮 32×32、图标 18px、用 `--navbar-muted` 上色,hover 用 `--navbar-hover-bg`。浮层容器、表单和输入框都用纸面/正文令牌,输入框需用与 Quarto 同等长的选择器(`.aa-DetachedContainer .aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input`)压过编译期暗色值;占位文字用 `--text-secondary`,取消按钮 `white-space: nowrap`,结果选中项用 `--surface-raised`。`≤575.98px` 时浮层收成贴顶通栏,左右无圆角,避免 Quarto 的桌面 `top:100px` 把搜索条压在正文中部。
|
|
91
|
+
- **色板切换**:`.palette-picker` 是 select-only combobox——按钮 `role="combobox"` + `aria-haspopup="listbox"`,面板 `.palette-menu-list` 为 `role="listbox"`,选项 `role="option"`;焦点留在按钮上,用 `aria-activedescendant` 指当前项。闭合态是 2rem 高胶囊:色点 + 英文名(Flexoki / Solarized / Hill Light)+ 方向箭头;展开后三行「色点 + 名称」,当前项右侧打勾。键位照 APG:↑/↓/Home/End 移动、首字母跳转、Enter 或 Space 提交、Esc 无提交关闭、Tab 关闭并走开。名称用英文,与 `book-palette` 的取值和色板目录同名,不另起中文译名。选择仍写 `book-palette`,首屏恢复逻辑不变,样式在 `css/nav.css`。不用原生 `<select>`(暗色下会保持系统浅色下拉)。
|
|
92
|
+
- **明暗圆钮**:Quarto 自带的是 16px「开关」位图(`bi-toggle-off/on` 的 data-URI `background-image`,填充色写死在 SVG 里),紧挨色板胶囊时两枚圆角疙瘩容易看混。主题把 `::before` 改成只做 `mask`、颜色吃 `currentColor` 的对比圆盘(描边 1.2、半径 6.2,实心半圆让到描边内缘),`.alternate`(夜间)旋转 180°,实心半圆换边;可点区域 44px、图标 16px。
|
|
93
|
+
- **四时辰**:山光选中时,胶囊右侧再出 `role="radiogroup"` 分段(`.mode-picker`):12px 线性图标 + 中文名(晓雾 / 午荫 / 暮烟 / 夜月,默认按 `byHour()` 就近选),roving tabindex、方向键移动并即时应用;切到其他色板即隐藏,Quarto 的明暗圆钮在山光下让位。`≤575.98px` 四时保持图标+短名,`≤419.98px` 先收掉仓库源图标,把宽度留给色板与四时,搜索不下行。
|
|
94
|
+
- **侧栏折叠箭头**:Quarto 的 `.sidebar-item-container` 是 `space-between`,part 标题那条规则又给链接 `flex: 1 1 0%`,箭头因此被推到侧栏最右缘、离标题一大片空白。主题把容器改 `justify-content: flex-start`,并用 `:has(> .sidebar-item-toggle)` 只收窄带箭头的行,箭头紧跟标题;不带箭头的 part 标题仍保持通栏底色。
|
|
72
95
|
- **color-scheme**:浅色声明 `light`,深色由 `body.quarto-dark` 覆盖,避免系统偏好渗入控件与内嵌 SVG。
|
|
73
96
|
- **纯文本代码块**:与语言块共用 `--code-*`;`text` 不启用语言 token。
|
|
97
|
+
- **公式**:MathJax 会把 `font-size: 94%` 写进 `mjx-container` 行内 style,主题用 `#quarto-document-content mjx-container { font-size: 1em !important }` 拉回与正文同档(17px),display 公式上下各留 1.3rem;行内公式与中文同基线,无需额外对齐。
|
|
98
|
+
- **代码标注**:`.code-annotation-gutter` 底色透明;行内编号与注释列表编号统一成 11px 描边圆圈,描边与数字用 `--accent`,注释正文 14px `--text-secondary`。Quarto 自带的 `code.sourceCode .code-annotation-anchor` 特异性高于主题同名单类选择器,覆盖必须写 `#quarto-document-content code.sourceCode .code-annotation-anchor`。
|
|
99
|
+
- **代码工具**:`.btn.code-tools-button` 是引导性小按钮(13px、`--text-secondary`、透明底、hover `--surface-raised`);它打开的是 Bootstrap 模态 `#quarto-code-tools-source`,模态面板用 `--surface-raised` 底 + `--card-border` 边 + `--radius-lg`,标题用黑体,内容区用 `--code-bg`(里面展示的是源文件),遮罩用 `--overlay-scrim`。Quarto 1.10.19 下 `code-fold` 不生成折叠加壳(只有 JS 残留),折叠样式无为而治,不要为它写选择器。
|
|
74
100
|
- **`.code-caption`**:次要说明色,紧贴对象;写作见 writing-quarto `authoring.md`。
|
|
75
|
-
- **可折叠答案**:`details.answer-disclosure`
|
|
101
|
+
- **可折叠答案**:`details.answer-disclosure` 默认收起,用上下发丝线、无圆角、无底色,像书页里的自测折页。
|
|
76
102
|
- **图**:Mermaid 与坐标图用令牌着色、字体随 `--ui-font`;围栏 `%%{init}%%` 用同栈短版;暗色不为白底图加滤镜。
|
|
103
|
+
- **令牌纪律**:样式里每个 `var(--…)` 都必须是色板 `tokens.css` 定义过的令牌。检查器新增断言 `css tokens all defined`,扫主题全部 `.css`/`.scss` 的 `var(--x)` 并减去所有 `--x:` 定义,不允许发明不存在的令牌(曾出现 `--text-primary`、`--surface`、`--text-tertiary` 这类「看着像有、实际透明」的引用,控件失去颜色还不报错)。
|
|
104
|
+
- **面板宽度与触摸目标**:交互面板宽度 `width: min(100%, 27rem)`,棋盘三列改成 `repeat(3, minmax(0, 1fr))` + 格子 `aspect-ratio: 1`,格子随卡片等比缩放(1280/768 → 121px,430 → 112,390 → 99,360 → 89,320 → 75),不再用 `vw` 猜屏宽;色板菜单项在 ≤575.98px 抬到 36px 一行、四时图标按钮 `min-width/min-height` 至少 24×28,菜单与胶囊都不出视口;源码模态 ≥576px 封顶 `min(1000px, 100vw - 2rem)` 并留 1rem 边距;行内代码在窄屏允许 `pre-wrap`,避免 `std::array<…>` 这类无空格类型名把正文列顶宽。
|
|
105
|
+
- **书页内交互面板**(cpp-board-games「运行效果」):面板本体是 `--surface-raised` 底 + `--card-border` 边的圆角卡;反馈行做成留言条——细边框 + 2px 左色条 + 状态点,`data-kind` 分 hint/warn/success 换色,不用裸灰字;「输入坐标」是模式开关,关闭时无框次要色、展开时 `--action-color` 描边并以 `aria-expanded` 同步;坐标输入行给 `行列` 等宽标签 + 两个数字位 + 「落子」按钮,帮助句常驻、报错时用 `:has()` 让帮助句让位、错误行带描边圆圈感叹号;程序输出是独立的终端窗(三点 + 标题 + 文件名 + 展开箭头,命令行走等宽字体),与面板之间留一道间隔,不再用原生 `details` 三角。
|
|
77
106
|
- **打印**:`pre` 恢复折行;屏幕横向滚动规则不动。
|
|
78
107
|
- **高对比偏好**:`prefers-contrast: more` 段与常规模式保持同一套强调与边框色。
|
|
79
108
|
|
|
80
109
|
## 设计来源
|
|
81
110
|
|
|
82
|
-
Quarto Book
|
|
111
|
+
Quarto Book 三栏;编译默认色板 `palettes/flexoki`(Flexoki Light / Dark),`palettes/solarized` 与 `palettes/hill-light`(山光四时)供读者运行时切换。实现为 Bootstrap cosmo/darkly + 主题 CSS。字体依据见标识 `bg-reading-surface-v1` 的知识文件。
|
|
83
112
|
|
|
84
113
|
## 主题结构与装配
|
|
85
114
|
|
|
@@ -90,25 +119,40 @@ Quarto Book 三栏;生产唯一色板 `palettes/github`:亮色对齐 Primer
|
|
|
90
119
|
| 文件 | 放什么 | 不放什么 |
|
|
91
120
|
|---|---|---|
|
|
92
121
|
| `palettes/<name>/theme-*.scss` | `$primary`、`$callout-color-*`、字体栈等 | 组件规则 |
|
|
93
|
-
| `palettes/<name>/tokens.css` |
|
|
94
|
-
| `palettes/<name>/
|
|
122
|
+
| `palettes/<name>/tokens.css` | 明暗语义颜色;Flexoki 挂 `body` / `body.quarto-dark`,Solarized 挂 `html[data-palette="solarized"]`,山光挂 `html[data-palette="hill-light"][data-mode="…"] body` | 结构尺度 |
|
|
123
|
+
| `palettes/<name>/brand-mark.svg` | 顶栏 mask 用的纯黑书标剪影 | 第二套外形、字母或折角 |
|
|
124
|
+
| `palettes/<name>/favicon-*.svg` | 明暗两份「打开的书」标签图标 | 运行时改色、`prefers-color-scheme` |
|
|
125
|
+
| `palettes/<name>/syntax.css` | Solarized 与山光的 `code span.*` 语法色覆盖 | 结构尺度、布局 |
|
|
126
|
+
| `palettes/<name>/meta.md` | 来源、highlight 映射、图标接线 | 运行时 CSS |
|
|
95
127
|
| `css/fonts.css` | `@font-face` 声明 | 字体栈选择 |
|
|
96
128
|
| `css/tokens.css` | 字号、半径、字体栈、`--content-width`、`color-scheme` 基线 | 色值、选择器 |
|
|
97
129
|
| `css/*.css`(除 tokens) | 组件规则;顺序 = `_quarto.yml` 的 `css:` | Bootstrap 变量 |
|
|
98
130
|
|
|
99
131
|
### 切换色板
|
|
100
132
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
133
|
+
默认(编译期)色板固定为 `flexoki`:
|
|
134
|
+
|
|
135
|
+
1. `_quarto.yml` 的 `theme.light/dark` 指到 `palettes/flexoki/theme-*.scss`。
|
|
136
|
+
2. `css:` 列表先写 `palettes/flexoki/tokens.css`,再写 `palettes/solarized/tokens.css`、`palettes/solarized/syntax.css`、`palettes/hill-light/tokens.css`、`palettes/hill-light/syntax.css`;顺序决定覆盖关系。
|
|
137
|
+
3. `highlight-style` 指到 Flexoki 目录的两份 `.theme`。
|
|
138
|
+
4. `include-in-header` 加 `includes/palette.html`:首屏恢复 `book-palette`(含山光的 `book-hill-mode`)与明暗,并按 `link[rel~="icon"]` 的现有相对前缀换 favicon。
|
|
139
|
+
5. `book.favicon` 指 `palettes/flexoki/favicon-light.svg`,另外三份 favicon 加进 `resources`;`footer.html` 的观察器在明暗/色板变化后再同步一次 favicon 与 theme-color。
|
|
140
|
+
6. 跑 `checking-layout.py`:色值按活跃 pack 表,并始终核 Solarized 覆盖层;`checking-dom.py` 的 C4 核四份 favicon 已发布。
|
|
141
|
+
|
|
142
|
+
Solarized 是运行时层,不进 `_quarto.yml` 的 theme/highlight-style:读者选择写 `html[data-palette="solarized"]`,`palettes/solarized/tokens.css` 覆盖语义色,`syntax.css` 覆盖 `code span.*`。它的 tokens 都带选择器前缀,因此不能直接当编译默认;要整本编成 Solarized,需要另做无前缀的 tokens 版本,再换 `theme` 与 `highlight-style`。
|
|
143
|
+
|
|
144
|
+
山光同样是运行时层,但比 Solarized 多一层状态:Quarto 只能编译一对 light/dark,山光有四种时辰(晓雾 / 午荫 / 暮烟 / 夜月,前三浅纸、夜月暗纸),所以四种模式全部由 `html[data-mode]` 在运行时选择,`tokens.css` 与 `syntax.css` 都带 `html[data-palette="hill-light"][data-mode="…"]` 前缀。
|
|
145
|
+
|
|
146
|
+
山光需要让 Quarto 的基座跟着时辰走:`includes/palette.html` 在 `<head>` 里按已存模式写 `quarto-color-scheme` 哨兵(夜月写 `alternate`,其余写 `default`),让 Quarto 的 before-body 脚本首帧就挂对 `quarto-light` / `quarto-dark`;运行时再由 `syncBase()` 调 `window.quartoToggleColorScheme()` 把 `body` 类与 `data-mode` 对齐(`applyPalette` / `applyMode` / 跨页恢复都会调)。夜月的 `body` 另声明 `color-scheme: dark`,滚动条与原生控件才跟着变暗。山光下 `includes/palette.html` 还会隐藏 Quarto 的明暗圆钮(明暗由时辰决定),并在色板分段右侧显示四时辰分段;favicon 的 `dark` 版本对应夜月。打印时夜月回落晓雾令牌(`tokens.css` 末尾的 `@media print`),纸面不出现深底。完整取值、对比度与偏离理由见 `palettes/hill-light/meta.md`。
|
|
105
147
|
|
|
106
148
|
### 页面结构约定
|
|
107
149
|
|
|
108
|
-
- 垂直节奏由正文容器与 section 的 `* + *` 控制,不对 `pre`/`p` 另设 `margin-bottom`。正文间距收成四档,档位按「两块内容是不是同一件事」取:**粘连 0.5rem**(标题→首段/列表、标题→callout、caption→其代码块)、**相关 1rem**(代码块↔caption、代码块↔callout、列表内代码块→验证句)、**换段 1.
|
|
150
|
+
- 垂直节奏由正文容器与 section 的 `* + *` 控制,不对 `pre`/`p` 另设 `margin-bottom`。正文间距收成四档,档位按「两块内容是不是同一件事」取:**粘连 0.5rem**(标题→首段/列表、标题→callout、caption→其代码块)、**相关 1rem**(代码块↔caption、代码块↔callout、列表内代码块→验证句)、**换段 1.4rem**(段落/列表/代码块默认)、**换节 3.25rem**(h2 之前;h3/h4/h5 之前 2.25rem)。h2 的 `margin-bottom` 与相邻 margin-top 折叠取大者,设 0.5rem 避免粘连档被抬高一倍。档位依据见标识 `bg-reading-surface-v1` 的知识文件。
|
|
109
151
|
- 顶栏与页面同底 + 底发丝线,用 `--navbar-*`。
|
|
110
|
-
-
|
|
111
|
-
-
|
|
152
|
+
- 正文链接常态与正文同色(Flexoki 墨色 / Solarized base01 / base1 / 山光墨色)+ 细下划线,hover 才转 `--link-hover-color`;不加 `:visited` 紫色。
|
|
153
|
+
- 表格用 booktabs:表头顶/底 1px、表头下 1px、无竖线、无斑马纹、tbody 无行线;`tbody` 末行底边也是 1px,与全站唯一的发丝线粗细一致(1.5px 已全部收回 1px)。
|
|
154
|
+
- 遮罩(搜索浮层、窄屏左栏)统一用 `--overlay-scrim`,亮色 0.42、暗色 0.62;不在组件里写 `rgba(0,0,0,*)`。
|
|
155
|
+
- 打印:`@page { size: A4; margin: 18mm 16mm }`;`pre` 恢复折行、不打印外链 URL;`figure` / `.callout` / `blockquote` 设 `break-inside: avoid`,`thead` 设 `display: table-header-group`;夜月打印回落晓雾令牌。
|
|
112
156
|
- 导航「Search / Source Code」英文默认值由 `includes/footer.html` 按 zh 同义补齐,只替换英文原文。
|
|
113
157
|
|
|
114
158
|
### 新增 callout
|
|
@@ -120,7 +164,9 @@ Quarto Book 三栏;生产唯一色板 `palettes/github`:亮色对齐 Primer
|
|
|
120
164
|
|
|
121
165
|
### 校验与高亮契约
|
|
122
166
|
|
|
123
|
-
- `checking-layout.py` 校验令牌与布局;发布用 `1280/768/390` 明暗与触屏、窄屏浮层。
|
|
124
|
-
- 高亮由 `_quarto.yml` 提供且与 palette `meta.md`
|
|
167
|
+
- `checking-layout.py` 校验令牌与布局;发布用 `1280/768/390/360` 明暗与触屏、窄屏浮层。
|
|
168
|
+
- 高亮由 `_quarto.yml` 提供且与 palette `meta.md` 一致(默认 `palettes/flexoki/highlight-light.theme` / `highlight-dark.theme`,取色自 Flexoki 官方 VS Code 主题);Solarized 的语法色由 `palettes/solarized/syntax.css` 在 `html[data-palette="solarized"]` 下覆盖,山光的由 `palettes/hill-light/syntax.css` 在 `html[data-palette="hill-light"][data-mode]` 下覆盖,都不改编译配置。注释色必须在本书代码底(亮 `#F2F0E5`、暗 `#1C1B1A`)上达到 4.5:1:亮色注释用 `#575653`(6.42:1),暗色用 `#878580`(4.67:1)。
|
|
125
169
|
- `text` 与语言块共用字体尺度;标题块用 `.code-with-filename`。
|
|
126
|
-
-
|
|
170
|
+
- 对比度断言:`checking-layout.py` 的 `palette text contrast >= 4.5:1` 逐色板逐模式检查六对——正文/次要/链接/代码前景对各自底色,外加行号对代码底、代码标题字对标题条;`prefers-contrast: more` 段跳过(那里本就更高)。山光行号原值 4.19–4.25:1(辅助信息,压一档到 4.6 以上),Solarized 代码标题字由派生表面配深/浅一档(亮 4.96、暗 5.55),理由记在各自 `meta.md` 的偏离表。
|
|
171
|
+
- 语法彩色 token 不在断言范围:Solarized 官方的注释 2.34、字符串 4.12、数字 2.97 属于调色板特征,只抬注释与标识符到可读线;山光派生语法色 4.19–4.36 同理,提高通道走 `prefers-contrast: more`。
|
|
172
|
+
- `checking-dom.py`:C0 palette↔highlight;复制按钮兄弟 DOM;触屏/打印;C4 四份 favicon;Mermaid SVG。
|