@chengzhao-dev/dsh-quarto-book 0.3.4 → 0.3.5

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.
@@ -1,63 +1,63 @@
1
- <div class="footer">
2
- © 2026 Quarto Book · 用 <a href="https://quarto.org">Quarto</a> 构建
3
- </div>
4
- <button id="back-to-top" type="button" title="返回顶部" aria-label="返回顶部">↑</button>
5
- <script>
6
- (function () {
7
- var btn = document.getElementById('back-to-top');
8
- if (!btn) return;
9
- var onScroll = function () {
10
- if (window.scrollY > 400) btn.classList.add('show');
11
- else btn.classList.remove('show');
12
- };
13
- window.addEventListener('scroll', onScroll, { passive: true });
14
- onScroll();
15
- btn.addEventListener('click', function () {
16
- window.scrollTo({ top: 0, behavior: 'smooth' });
17
- });
18
- })();
19
- </script>
20
- <script>
21
- (function () {
22
- var meta = document.getElementById('meta-theme-color');
23
- if (!meta) return;
24
- // 地址栏主题色直接读 tokens.css 的 --page-bg 计算值(body.quarto-dark 切换后自动取暗色),
25
- // 避免与令牌双写漂移;取不到时按当前明暗兜底
26
- var sync = function () {
27
- var v = window.getComputedStyle(document.body).getPropertyValue('--page-bg').trim();
28
- if (!v) v = document.body.classList.contains('quarto-dark') ? '#22272E' : '#FFFFFF';
29
- meta.setAttribute('content', v);
30
- };
31
- sync();
32
- if (window.MutationObserver) {
33
- new MutationObserver(sync).observe(document.body, { attributes: true, attributeFilter: ['class'] });
34
- }
35
- })();
36
- </script>
37
- <script>
38
- (function () {
39
- // Quarto 只本地化搜索结果面板文案,导航栏搜索按钮与仓库图标仍带组件库的英文默认值。
40
- // 这里按 zh 语言包的同义中文补齐,只在命中英文原文时替换,Quarto 自行本地化后本脚本自动失效。
41
- var LABELS = { 'Search': '搜索', 'Source Code': '查看代码' };
42
- var ATTRS = ['title', 'aria-label', 'placeholder'];
43
- var sync = function () {
44
- document
45
- .querySelectorAll('a.quarto-navigation-tool, #quarto-search, #quarto-search *')
46
- .forEach(function (el) {
47
- ATTRS.forEach(function (attr) {
48
- var text = el.getAttribute(attr);
49
- if (text && LABELS[text]) {
50
- el.setAttribute(attr, LABELS[text]);
51
- }
52
- });
53
- });
54
- };
55
- sync();
56
- window.addEventListener('load', sync);
57
- var box = document.getElementById('quarto-search');
58
- if (box && window.MutationObserver) {
59
- new MutationObserver(sync).observe(box, { childList: true, subtree: true });
60
- }
61
- })();
62
- </script>
63
-
1
+ <div class="footer">
2
+ © 2026 Quarto Book · 用 <a href="https://quarto.org">Quarto</a> 构建
3
+ </div>
4
+ <button id="back-to-top" type="button" title="返回顶部" aria-label="返回顶部">↑</button>
5
+ <script>
6
+ (function () {
7
+ var btn = document.getElementById('back-to-top');
8
+ if (!btn) return;
9
+ var onScroll = function () {
10
+ if (window.scrollY > 400) btn.classList.add('show');
11
+ else btn.classList.remove('show');
12
+ };
13
+ window.addEventListener('scroll', onScroll, { passive: true });
14
+ onScroll();
15
+ btn.addEventListener('click', function () {
16
+ window.scrollTo({ top: 0, behavior: 'smooth' });
17
+ });
18
+ })();
19
+ </script>
20
+ <script>
21
+ (function () {
22
+ var meta = document.getElementById('meta-theme-color');
23
+ if (!meta) return;
24
+ // 地址栏主题色直接读 tokens.css 的 --page-bg 计算值(body.quarto-dark 切换后自动取暗色),
25
+ // 避免与令牌双写漂移;取不到时按当前明暗兜底
26
+ var sync = function () {
27
+ var v = window.getComputedStyle(document.body).getPropertyValue('--page-bg').trim();
28
+ if (!v) v = document.body.classList.contains('quarto-dark') ? '#22272E' : '#FFFFFF';
29
+ meta.setAttribute('content', v);
30
+ };
31
+ sync();
32
+ if (window.MutationObserver) {
33
+ new MutationObserver(sync).observe(document.body, { attributes: true, attributeFilter: ['class'] });
34
+ }
35
+ })();
36
+ </script>
37
+ <script>
38
+ (function () {
39
+ // Quarto 只本地化搜索结果面板文案,导航栏搜索按钮与仓库图标仍带组件库的英文默认值。
40
+ // 这里按 zh 语言包的同义中文补齐,只在命中英文原文时替换,Quarto 自行本地化后本脚本自动失效。
41
+ var LABELS = { 'Search': '搜索', 'Source Code': '查看代码' };
42
+ var ATTRS = ['title', 'aria-label', 'placeholder'];
43
+ var sync = function () {
44
+ document
45
+ .querySelectorAll('a.quarto-navigation-tool, #quarto-search, #quarto-search *')
46
+ .forEach(function (el) {
47
+ ATTRS.forEach(function (attr) {
48
+ var text = el.getAttribute(attr);
49
+ if (text && LABELS[text]) {
50
+ el.setAttribute(attr, LABELS[text]);
51
+ }
52
+ });
53
+ });
54
+ };
55
+ sync();
56
+ window.addEventListener('load', sync);
57
+ var box = document.getElementById('quarto-search');
58
+ if (box && window.MutationObserver) {
59
+ new MutationObserver(sync).observe(box, { childList: true, subtree: true });
60
+ }
61
+ })();
62
+ </script>
63
+
@@ -1,38 +1,38 @@
1
- # Palette: github
2
-
3
- 生产默认(唯一)色板。亮色对齐 GitHub Primer Light Default;暗色对齐 GitHub Primer **Dark Dimmed**(软暗色:近灰底 `#22272E`,缓解 Dark Default `#0D1117` 的偏黑与光晕)。代码语法色用色板目录里的两份 skylighting 主题 `highlight-light.theme` / `highlight-dark.theme`,取色自 Primer 当前 prettylights([primer/github-vscode-theme](https://github.com/primer/github-vscode-theme) 的 light 与 dark-dimmed),不再用 Quarto 内置的 2020 年 `github-light` / `github-dark`。两处抬色:暗色注释从官方 `#768390` 抬到 `#9AA1AB`(本书代码底上需 4.5:1),暗色关键字改用 Dark Default 的关键字红 `#FF7B72`;取舍见标识 `bg-reading-surface-v1` 的知识文件。
4
-
5
- ## 接线
6
-
7
- | 项 | 路径 / 值 |
8
- | --- | --- |
9
- | tokens | `palettes/github/tokens.css` |
10
- | SCSS light | `palettes/github/theme-light.scss` |
11
- | SCSS dark | `palettes/github/theme-dark.scss` |
12
- | highlight light | `assets/theme/palettes/github/highlight-light.theme` |
13
- | highlight dark | `assets/theme/palettes/github/highlight-dark.theme` |
14
-
15
- ## 暗色分层(Dark Dimmed)
16
-
17
- | 表面 | 色值 |
18
- | --- | --- |
19
- | page / navbar(最深) | `#22272E` |
20
- | surface-raised / code / card | `#2D333B` |
21
- | 代码标题条 | `#373E47` |
22
- | 边框 | `#444C56` |
23
- | 正文 / 次要文字 | `#CDD9E5` / `#B1BAC4` |
24
- | 链接 | `#539BF5` |
25
-
26
- 2026-09 软化:暗色自 Dark Default 迁至 Dimmed;圆角抬升(sm 8px / md·lg 12px / 代码块 8px);首页卡片亮色加轻阴影;正文与代码行高 1.75;表头去大写;品牌与卡片标题 700→600。
27
-
28
- ## 切换
29
-
30
- 生产固定本 pack,不做第二套色板。若未来换 pack:在 `_quarto.yml` 中把 theme SCSS、palette tokens 与 `highlight-style` 改成目标 pack;共享 `css/*.css`、字体与 includes 不动。
31
-
32
- ## 来源
33
-
34
- - [Primer Color usage](https://primer.style/product/getting-started/foundations/color-usage/)
35
- - [primer/github-vscode-theme](https://github.com/primer/github-vscode-theme)(prettylights 取色来源,light 与 dark-dimmed)
36
- - GitHub Light / Dark Dimmed 文档表面色
37
-
38
- 这套主题由本插件维护。项目若复制了主题资产,改动的语法色主题(`highlight-light.theme`、`highlight-dark.theme`)与 `meta.md` 接线表只同步到项目 `_quarto.yml` 实际引用的那份副本。
1
+ # Palette: github
2
+
3
+ 生产默认(唯一)色板。亮色对齐 GitHub Primer Light Default;暗色对齐 GitHub Primer **Dark Dimmed**(软暗色:近灰底 `#22272E`,缓解 Dark Default `#0D1117` 的偏黑与光晕)。代码语法色用色板目录里的两份 skylighting 主题 `highlight-light.theme` / `highlight-dark.theme`,取色自 Primer 当前 prettylights([primer/github-vscode-theme](https://github.com/primer/github-vscode-theme) 的 light 与 dark-dimmed),不再用 Quarto 内置的 2020 年 `github-light` / `github-dark`。两处抬色:暗色注释从官方 `#768390` 抬到 `#9AA1AB`(本书代码底上需 4.5:1),暗色关键字改用 Dark Default 的关键字红 `#FF7B72`;取舍见标识 `bg-reading-surface-v1` 的知识文件。
4
+
5
+ ## 接线
6
+
7
+ | 项 | 路径 / 值 |
8
+ | --- | --- |
9
+ | tokens | `palettes/github/tokens.css` |
10
+ | SCSS light | `palettes/github/theme-light.scss` |
11
+ | SCSS dark | `palettes/github/theme-dark.scss` |
12
+ | highlight light | `assets/theme/palettes/github/highlight-light.theme` |
13
+ | highlight dark | `assets/theme/palettes/github/highlight-dark.theme` |
14
+
15
+ ## 暗色分层(Dark Dimmed)
16
+
17
+ | 表面 | 色值 |
18
+ | --- | --- |
19
+ | page / navbar(最深) | `#22272E` |
20
+ | surface-raised / code / card | `#2D333B` |
21
+ | 代码标题条 | `#373E47` |
22
+ | 边框 | `#444C56` |
23
+ | 正文 / 次要文字 | `#CDD9E5` / `#B1BAC4` |
24
+ | 链接 | `#539BF5` |
25
+
26
+ 2026-09 软化:暗色自 Dark Default 迁至 Dimmed;圆角抬升(sm 8px / md·lg 12px / 代码块 8px);首页卡片亮色加轻阴影;正文与代码行高 1.75;表头去大写;品牌与卡片标题 700→600。
27
+
28
+ ## 切换
29
+
30
+ 生产固定本 pack,不做第二套色板。若未来换 pack:在 `_quarto.yml` 中把 theme SCSS、palette tokens 与 `highlight-style` 改成目标 pack;共享 `css/*.css`、字体与 includes 不动。
31
+
32
+ ## 来源
33
+
34
+ - [Primer Color usage](https://primer.style/product/getting-started/foundations/color-usage/)
35
+ - [primer/github-vscode-theme](https://github.com/primer/github-vscode-theme)(prettylights 取色来源,light 与 dark-dimmed)
36
+ - GitHub Light / Dark Dimmed 文档表面色
37
+
38
+ 这套主题由本插件维护。项目若复制了主题资产,改动的语法色主题(`highlight-light.theme`、`highlight-dark.theme`)与 `meta.md` 接线表只同步到项目 `_quarto.yml` 实际引用的那份副本。
@@ -1,68 +1,68 @@
1
- ---
2
- kb_id: "bg-reading-surface-v1"
3
- title: "阅读表面:字体、栏宽与强调"
4
- domain: "visual-theme"
5
- tags: [fonts, typography, layout, theme, readability, contrast]
6
- level_range: [0, 5]
7
- dependencies: []
8
- created: "2026-10-10"
9
- updated: "2026-10-12"
10
- chunk_strategy: "semantic_heading"
11
- estimated_tokens: 1500
12
- ---
13
-
14
- # 阅读表面:字体、栏宽与强调
15
-
16
- 本文件回答这本书的阅读表面为什么这样定:正文字体、正文栏宽、窄屏行为与加粗/链接颜色。怎么做(改哪一步、动哪个文件)见 `designing-theme` 技能的 `references/theme-spine.md`,数值与实现见 `references/theme-system.md`。本文件只放理由。这套主题由本插件维护,不与其他仓库共享;项目若复制了资产,以项目 `_quarto.yml` 实际引用的副本为准。
17
-
18
- ## 正文为什么是 LXGW 的单一字面
19
-
20
- 中文保持霞鹜文楷路线(楷体),不换黑体:这本书是长时间连续阅读的技术书,楷体的笔画变化比几何无衬线更耐读;作者「文楷不适合超长正文」的评价针对的是屏幕上偏细的 Regular,不构成换字体的理由——用 Bright 的 Medium 解决偏细。
21
-
22
- ### 为什么合并成一份 Bright Medium
23
-
24
- 旧方案是「Fixel Text(拉丁)+ 文楷 Screen(中文)」双字体拼接:Fixel 是几何无衬线、没有 400 字重,与楷体的笔形对不上;两套西文与中文各算各的基线,混排节奏不一致。LXGW Bright 本身就是「Ysabeau Office(西文,齐线数字)+ 文楷中等笔画(中文)」的合并字体,一个文件解决拼接问题;全站只挂这一个字面,层级靠字号,标题请求 600 时在全站 `font-synthesis: none` 下仍落到这一份,不合成假粗体。
25
-
26
- ### 为什么不用文楷 Screen 与系统西文
27
-
28
- 文楷 Screen 是给「系统里已有 Segoe/Roboto」的场景准备的:它的度量对齐 Roboto、Medium 笔画标成 Regular。本站中西文都自托管,继续「文楷 Screen + 另一套西文」会回到双基线拼接。Bright Code 的西文是收窄的 Monaspace Argon(与汉字宽约 1:2),所以代码字体保持 Bright Code 不变。
29
-
30
- ### 代码西文与正文西文为什么不是同一个设计
31
-
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),代码里的汉字笔画与正文同一档,不是「代码更细」。因此不因「代码西文与正文西文不同源」换字体,也不为对齐西文改用黑体路线的等宽字。
33
-
34
- ### 排除的候选
35
-
36
- Inter、思源黑体、JetBrains Mono、Cascadia、Iosevka、Inconsolata 均不采用:前两者是黑体路线(与「中文保持楷体」冲突),后四者是代码字体(代码已有 Bright Code)。Roboto 与 Segoe UI 是 Apache/微软许可,不满足本书「只收 OFL 到 `assets/theme/assets/fonts/`」的政策。旧式数字(Ysabeau Infant 一系)不适合和汉字混排,不用于这本书。
37
-
38
- ## 栏宽为什么是 872px(内容列 840px)
39
-
40
- Bright Code 在 16px 下每个 ASCII 字符前进 8px,代码区内边距左右各 16px、边框左右各 1px,100 列代码需要 100×8+32+2=834px 的内容宽。Quarto 会从 `body-width` 中再减去两侧各 1rem 的栅格内边距(内容列 = body-width − 32px),因此 `body-width` 取 872px,内容列 840px、代码文本区 806px,留约 6px 余量。栏宽随代码列宽走而不是随显示器走:宽视口只增大外侧留白,正文行长保持在可读范围(WCAG 建议不超过约 80 个拉丁字母或 40 个汉字)。标题下的 description 副标题与正文段落同一内容列,不再用 `ch` 二次限宽(Bright 的西文是比例字体,`ch` 只量出半个汉字宽,会先于正文折行)。
41
-
42
- ## 正文间距为什么收成四档
43
-
44
- 全站块间距只有四档:粘连 0.5rem、相关 1rem、换段 1.5rem、换节 3rem(h3/h4/h5 前 2rem)。档位按「两块内容是不是同一件事」取:标题与它的首段、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
-
46
- ## 窄屏为什么只让代码块横向滚动
47
-
48
- 125%/150% 缩放后 CSS 像素变少,栏宽由 Quarto 按断点缩小;此时若代码跟着折行,同一行代码在宽窄屏上的断点不同,读者对照截图与本地输出时会错位。固定 `white-space: pre` + 块内 `overflow-x: auto`,代码行在任何视口下保持完整;正文段落照常折行。打印时横向滚动不存在,打印样式把 `pre` 恢复为折行,屏幕规则不动。内容列 840px 只比 834px 多 6px:若 Windows 滚动条或亚像素取整吃掉余量导致第 100 列被裁,再把 `body-width` 升到约 880px,不预先加宽。
49
-
50
- ## 加粗为什么仍合成且不用链接色
51
-
52
- 书里的 `**` 大量用作列表小标题(「出错的原因」「正确的做法」)和行内强调;Bright 只有一个字面,若同时去掉合成加粗和强调色,这些字与正文无差别。因此:`strong` 保留 `font-synthesis: weight` 的合成(全站唯一放开点),配一个比正文更实的强调色(亮更深、暗更亮),且强调色不取链接蓝——加粗必须和链接在明暗两套下都能区分。列表里独占一段的 `**` 小标题保持正文色块级形态,避免一列蓝标题;代码文件名、行内代码、kbd 各用自己令牌,不被强调色或链接色串染。
53
-
54
- ## 颜色与对比度的取值依据
55
-
56
- 色板不换:亮色 Primer Light、暗色 Primer Dark(Dimmed 软暗)。callout 条色收敛到页面已有功能色(链接蓝、成功绿、低饱和琥珀与红、Primer 紫),浅底用同色 8%–12% 透明。文本对比度按 WCAG 2.2 的 1.4.3(4.5:1)校验:正文、强调、链接、13px 表头、14px 图注与代码标题在各自底色上低于 4.5:1 时升到更实的一档,不改成纯黑或纯白,也不借用链接蓝。
57
-
58
- ## 已记录的偏低对比项
59
-
60
- 暗色代码高亮的注释色已抬到 `#9AA1AB`(本书代码底 `#2D333B` 上约 4.89:1,达到 4.5:1,仍暗于次要文字 `#B1BAC4` 的 6.49:1,注释看起来比正文淡);旧值 `#768390`(官方 Dimmed 注释色,约 3.29:1)不再使用。亮色正文行号用 `#57606A`、警告琥珀用 `#8A5C00`,是按同一 4.5:1 口径从原值升档的结果。
61
-
62
- ## 明暗代码色跟哪一对 GitHub 主题
63
-
64
- 页面色和语法色来自同一对 Primer 主题:亮色 Primer Light Default、暗色 Primer Dark Dimmed。代码语法色不使用 Quarto 内置的 `github-light` / `github-dark`——那是 2020 年的 skylighting 主题,亮色按白底 `#FFFFFF` 设计、暗色按早已弃用的旧深色底 `#24292E` 设计,叠在本书的代码底(亮 `#F6F8FA`、暗 `#2D333B`)上是两代主题错层;语法色改由色板目录的 `highlight-light.theme` / `highlight-dark.theme` 提供,取色自 Primer 当前 prettylights(primer/github-vscode-theme 的 light 与 dark-dimmed),`BackgroundColor` 与 `--code-bg` 相同,CSS 仍不覆盖 `span` 色。
65
-
66
- 三处允许偏离官方 prettylights,其余照抄:暗色普通文本用 `#CDD9E5`(与 `--code-fg` 和纯文本块一致,不用官方 `#ADBAC7`);暗色注释一族从官方 `#768390`(约 3.29:1)抬到 `#9AA1AB`(约 4.89:1)——中文注释是这本书的阅读对象,必须过 4.5:1;暗色关键字一族改用 Dark Default 的关键字红 `#FF7B72`(约 5.05:1,官方 Dimmed 红 `#F47067` 在本书代码底上约 4.47:1 贴线)。亮色整表取 Primer Light:注释 `#57606A`(约 6.0:1,与行号同档)、关键字 `#CF222E`(约 5.03:1)、普通文本 `#1F2328`(与 `--code-fg` 一致),旧表的 `#6A737D` 注释与 `#D73A49` 关键字都不再用。
67
-
68
- 不把暗色整页换回 Dark Default(`#0D1117`)的原因:近黑底上注释对比更好(约 6.15:1),但近黑正是本书从 Dark Default 迁到 Dimmed 的原因——中文长文的正文面积大于代码,长文光晕比代码对比更伤阅读;所以保留 Dimmed 页面,注释对比用抬一档灰补齐,关键字用 Dark Default 的红补齐,不整页翻案。
1
+ ---
2
+ kb_id: "bg-reading-surface-v1"
3
+ title: "阅读表面:字体、栏宽与强调"
4
+ domain: "visual-theme"
5
+ tags: [fonts, typography, layout, theme, readability, contrast]
6
+ level_range: [0, 5]
7
+ dependencies: []
8
+ created: "2026-10-10"
9
+ updated: "2026-10-12"
10
+ chunk_strategy: "semantic_heading"
11
+ estimated_tokens: 1500
12
+ ---
13
+
14
+ # 阅读表面:字体、栏宽与强调
15
+
16
+ 本文件回答这本书的阅读表面为什么这样定:正文字体、正文栏宽、窄屏行为与加粗/链接颜色。怎么做(改哪一步、动哪个文件)见 `designing-theme` 技能的 `references/theme-spine.md`,数值与实现见 `references/theme-system.md`。本文件只放理由。这套主题由本插件维护,不与其他仓库共享;项目若复制了资产,以项目 `_quarto.yml` 实际引用的副本为准。
17
+
18
+ ## 正文为什么是 LXGW 的单一字面
19
+
20
+ 中文保持霞鹜文楷路线(楷体),不换黑体:这本书是长时间连续阅读的技术书,楷体的笔画变化比几何无衬线更耐读;作者「文楷不适合超长正文」的评价针对的是屏幕上偏细的 Regular,不构成换字体的理由——用 Bright 的 Medium 解决偏细。
21
+
22
+ ### 为什么合并成一份 Bright Medium
23
+
24
+ 旧方案是「Fixel Text(拉丁)+ 文楷 Screen(中文)」双字体拼接:Fixel 是几何无衬线、没有 400 字重,与楷体的笔形对不上;两套西文与中文各算各的基线,混排节奏不一致。LXGW Bright 本身就是「Ysabeau Office(西文,齐线数字)+ 文楷中等笔画(中文)」的合并字体,一个文件解决拼接问题;全站只挂这一个字面,层级靠字号,标题请求 600 时在全站 `font-synthesis: none` 下仍落到这一份,不合成假粗体。
25
+
26
+ ### 为什么不用文楷 Screen 与系统西文
27
+
28
+ 文楷 Screen 是给「系统里已有 Segoe/Roboto」的场景准备的:它的度量对齐 Roboto、Medium 笔画标成 Regular。本站中西文都自托管,继续「文楷 Screen + 另一套西文」会回到双基线拼接。Bright Code 的西文是收窄的 Monaspace Argon(与汉字宽约 1:2),所以代码字体保持 Bright Code 不变。
29
+
30
+ ### 代码西文与正文西文为什么不是同一个设计
31
+
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),代码里的汉字笔画与正文同一档,不是「代码更细」。因此不因「代码西文与正文西文不同源」换字体,也不为对齐西文改用黑体路线的等宽字。
33
+
34
+ ### 排除的候选
35
+
36
+ Inter、思源黑体、JetBrains Mono、Cascadia、Iosevka、Inconsolata 均不采用:前两者是黑体路线(与「中文保持楷体」冲突),后四者是代码字体(代码已有 Bright Code)。Roboto 与 Segoe UI 是 Apache/微软许可,不满足本书「只收 OFL 到 `assets/theme/assets/fonts/`」的政策。旧式数字(Ysabeau Infant 一系)不适合和汉字混排,不用于这本书。
37
+
38
+ ## 栏宽为什么是 872px(内容列 840px)
39
+
40
+ Bright Code 在 16px 下每个 ASCII 字符前进 8px,代码区内边距左右各 16px、边框左右各 1px,100 列代码需要 100×8+32+2=834px 的内容宽。Quarto 会从 `body-width` 中再减去两侧各 1rem 的栅格内边距(内容列 = body-width − 32px),因此 `body-width` 取 872px,内容列 840px、代码文本区 806px,留约 6px 余量。栏宽随代码列宽走而不是随显示器走:宽视口只增大外侧留白,正文行长保持在可读范围(WCAG 建议不超过约 80 个拉丁字母或 40 个汉字)。标题下的 description 副标题与正文段落同一内容列,不再用 `ch` 二次限宽(Bright 的西文是比例字体,`ch` 只量出半个汉字宽,会先于正文折行)。
41
+
42
+ ## 正文间距为什么收成四档
43
+
44
+ 全站块间距只有四档:粘连 0.5rem、相关 1rem、换段 1.5rem、换节 3rem(h3/h4/h5 前 2rem)。档位按「两块内容是不是同一件事」取:标题与它的首段、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
+
46
+ ## 窄屏为什么只让代码块横向滚动
47
+
48
+ 125%/150% 缩放后 CSS 像素变少,栏宽由 Quarto 按断点缩小;此时若代码跟着折行,同一行代码在宽窄屏上的断点不同,读者对照截图与本地输出时会错位。固定 `white-space: pre` + 块内 `overflow-x: auto`,代码行在任何视口下保持完整;正文段落照常折行。打印时横向滚动不存在,打印样式把 `pre` 恢复为折行,屏幕规则不动。内容列 840px 只比 834px 多 6px:若 Windows 滚动条或亚像素取整吃掉余量导致第 100 列被裁,再把 `body-width` 升到约 880px,不预先加宽。
49
+
50
+ ## 加粗为什么仍合成且不用链接色
51
+
52
+ 书里的 `**` 大量用作列表小标题(「出错的原因」「正确的做法」)和行内强调;Bright 只有一个字面,若同时去掉合成加粗和强调色,这些字与正文无差别。因此:`strong` 保留 `font-synthesis: weight` 的合成(全站唯一放开点),配一个比正文更实的强调色(亮更深、暗更亮),且强调色不取链接蓝——加粗必须和链接在明暗两套下都能区分。列表里独占一段的 `**` 小标题保持正文色块级形态,避免一列蓝标题;代码文件名、行内代码、kbd 各用自己令牌,不被强调色或链接色串染。
53
+
54
+ ## 颜色与对比度的取值依据
55
+
56
+ 色板不换:亮色 Primer Light、暗色 Primer Dark(Dimmed 软暗)。callout 条色收敛到页面已有功能色(链接蓝、成功绿、低饱和琥珀与红、Primer 紫),浅底用同色 8%–12% 透明。文本对比度按 WCAG 2.2 的 1.4.3(4.5:1)校验:正文、强调、链接、13px 表头、14px 图注与代码标题在各自底色上低于 4.5:1 时升到更实的一档,不改成纯黑或纯白,也不借用链接蓝。
57
+
58
+ ## 已记录的偏低对比项
59
+
60
+ 暗色代码高亮的注释色已抬到 `#9AA1AB`(本书代码底 `#2D333B` 上约 4.89:1,达到 4.5:1,仍暗于次要文字 `#B1BAC4` 的 6.49:1,注释看起来比正文淡);旧值 `#768390`(官方 Dimmed 注释色,约 3.29:1)不再使用。亮色正文行号用 `#57606A`、警告琥珀用 `#8A5C00`,是按同一 4.5:1 口径从原值升档的结果。
61
+
62
+ ## 明暗代码色跟哪一对 GitHub 主题
63
+
64
+ 页面色和语法色来自同一对 Primer 主题:亮色 Primer Light Default、暗色 Primer Dark Dimmed。代码语法色不使用 Quarto 内置的 `github-light` / `github-dark`——那是 2020 年的 skylighting 主题,亮色按白底 `#FFFFFF` 设计、暗色按早已弃用的旧深色底 `#24292E` 设计,叠在本书的代码底(亮 `#F6F8FA`、暗 `#2D333B`)上是两代主题错层;语法色改由色板目录的 `highlight-light.theme` / `highlight-dark.theme` 提供,取色自 Primer 当前 prettylights(primer/github-vscode-theme 的 light 与 dark-dimmed),`BackgroundColor` 与 `--code-bg` 相同,CSS 仍不覆盖 `span` 色。
65
+
66
+ 三处允许偏离官方 prettylights,其余照抄:暗色普通文本用 `#CDD9E5`(与 `--code-fg` 和纯文本块一致,不用官方 `#ADBAC7`);暗色注释一族从官方 `#768390`(约 3.29:1)抬到 `#9AA1AB`(约 4.89:1)——中文注释是这本书的阅读对象,必须过 4.5:1;暗色关键字一族改用 Dark Default 的关键字红 `#FF7B72`(约 5.05:1,官方 Dimmed 红 `#F47067` 在本书代码底上约 4.47:1 贴线)。亮色整表取 Primer Light:注释 `#57606A`(约 6.0:1,与行号同档)、关键字 `#CF222E`(约 5.03:1)、普通文本 `#1F2328`(与 `--code-fg` 一致),旧表的 `#6A737D` 注释与 `#D73A49` 关键字都不再用。
67
+
68
+ 不把暗色整页换回 Dark Default(`#0D1117`)的原因:近黑底上注释对比更好(约 6.15:1),但近黑正是本书从 Dark Default 迁到 Dimmed 的原因——中文长文的正文面积大于代码,长文光晕比代码对比更伤阅读;所以保留 Dimmed 页面,注释对比用抬一档灰补齐,关键字用 Dark Default 的红补齐,不整页翻案。