@chengzhao-dev/dsh-quarto-book 0.6.1 → 0.6.3
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 +60 -31
- package/README.md +53 -24
- package/lib/tools/render-check.js +1 -1
- package/package.json +5 -2
- package/skills/designing-theme/assets/theme/assets/fonts/lxgw-bright-code-common.woff2 +0 -0
- package/skills/designing-theme/assets/theme/assets/fonts/lxgw-bright-medium-common.woff2 +0 -0
- package/skills/designing-theme/assets/theme/css/mermaid.css +5 -6
- package/skills/designing-theme/knowledge/reading-surface.md +1 -1
- package/skills/designing-theme/references/theme-system.md +5 -5
- package/skills/designing-theme/scripts/checking-layout.py +49 -9
- package/skills/writing-quarto/SKILL.md +2 -2
- package/skills/writing-quarto/examples/02-structure-shape.md +54 -12
- package/skills/writing-quarto/examples/03-block-after.md +14 -0
- package/skills/writing-quarto/examples/03-qmd-elements.md +16 -0
- package/skills/writing-quarto/examples/04-paragraph-cases.md +14 -0
- package/skills/writing-quarto/examples/04-paragraph-opening.md +2 -2
- package/skills/writing-quarto/examples/05-sentence-frame.md +4 -4
- package/skills/writing-quarto/examples/05-sentence-reference.md +14 -0
- package/skills/writing-quarto/examples/06-wording-cases.md +37 -0
- package/skills/writing-quarto/examples/{03-layout-list.md → 07-layout-list.md} +14 -0
- package/skills/writing-quarto/examples/08-appendix.md +2 -2
- package/skills/writing-quarto/quarto/authoring.md +4 -4
- package/skills/writing-quarto/quarto/basics.md +17 -17
- package/skills/writing-quarto/quarto/mermaid.md +41 -5
- package/skills/writing-quarto/quarto/prose.md +25 -2
- package/skills/writing-quarto/quarto/terminal.md +1 -1
- package/skills/writing-quarto/scripts/testing-content.py +199 -1
- package/skills/writing-quarto/scripts/verifying-content.py +281 -0
- package/skills/writing-quarto/steps/02-structure.md +9 -26
- package/skills/writing-quarto/steps/03-blocks.md +31 -20
- package/skills/writing-quarto/steps/04-paragraphs.md +35 -18
- package/skills/writing-quarto/steps/05-sentences.md +24 -14
- package/skills/writing-quarto/steps/06-wording.md +37 -0
- package/skills/writing-quarto/steps/07-layout.md +12 -13
- package/skills/writing-quarto/steps/08-reread.md +7 -4
- package/skills/writing-quarto/steps/09-check.md +3 -3
- package/templates/quarto-book-project/SKILL.md +1 -1
- package/templates/quarto-book-project/checks.json +5 -0
- package/templates/quarto-book-project/writing/chapter-map.md +3 -0
package/README.en.md
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
# dsh-quarto-book
|
|
2
2
|
|
|
3
3
|
[](https://github.com/chengzhao-dev/dsh-quarto-book/actions/workflows/publish.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@chengzhao-dev/dsh-quarto-book)
|
|
4
5
|
|
|
5
6
|
**English** | [简体中文](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/README.md)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- Write `.qmd`: `writing-quarto` covers the chapter skeleton, structure and Chinese prose.
|
|
10
|
-
- Change the theme: `designing-theme` covers CSS, fonts and palettes.
|
|
11
|
-
- Check rendered HTML: `quarto_render_check` judges publishability once, and `quarto_pass_report` prints the closing receipt.
|
|
8
|
+
Write Chinese technical chapters in a Quarto Book repository: `writing-quarto` owns the chapter skeleton and prose, `designing-theme` owns the theme. Both skills appear only inside `type: book` repositories. After a render, `quarto_render_check` decides whether the HTML is publishable and `quarto_pass_report` prints the closing receipt.
|
|
12
9
|
|
|
13
10
|
## What it provides
|
|
14
11
|
|
|
@@ -19,31 +16,51 @@ Polish Chinese technical chapters, check book structure and mixed Chinese-Englis
|
|
|
19
16
|
| `quarto_render_check` | Check that `output-dir` is safe, render once when asked, and inspect HTML in `_book/` for publishing | Editing `.qmd`, fixing config automatically, or re-running a failed render |
|
|
20
17
|
| `quarto_pass_report` | Compress the run into a fixed-line receipt card: skill, mode, files and steps changed, items held, check verdicts | Saving to disk, quoting chapter prose, or changing the text based on the receipt |
|
|
21
18
|
|
|
22
|
-
For when the skills appear and which rule each step maps to, see [docs/plugin-flow.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-flow.md). It is a human-facing walkthrough, not the rule source used while a skill runs.
|
|
23
|
-
|
|
24
19
|
Both skills are discovered from the package's `skills/` directory and loaded on demand. Relative paths inside a skill resolve against that skill's directory: `writing-quarto` uses `steps/`, `examples/`, `quarto/`, `scripts/`; `designing-theme` uses `references/`, `knowledge/`, `assets/`, `scripts/`.
|
|
25
20
|
|
|
26
|
-
##
|
|
21
|
+
## Quick start
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
```
|
|
23
|
+
1. Install the plugin:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
dsh plugin --profile web add npm:@chengzhao-dev/dsh-quarto-book@latest
|
|
27
|
+
```
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
2. Open a session in the book repository. `_quarto.yml` needs a standalone `type: book` line, and the book needs at least one `.qmd` or `.md` chapter source; only then do both skill names appear.
|
|
30
|
+
3. Call a skill: `writing-quarto` for prose, `designing-theme` for the theme.
|
|
31
|
+
|
|
32
|
+
Replace `--profile` with the profile you actually run. The desktop app always runs the `desktop` profile, and that profile is owned by the app, so `dsh --profile desktop` is rejected; install or upgrade with `dsh plugin --profile desktop add <package>`, and use the app's Settings → Plugins → Add plugin only if the app refuses that write. To pin a version, write `npm:@chengzhao-dev/dsh-quarto-book@0.6.3`; to follow a GitHub tag, write `github:chengzhao-dev/dsh-quarto-book#v0.6.3`.
|
|
33
33
|
|
|
34
34
|
Upgrading from the old unscoped package `dsh-quarto-book` (removed from npm with 0.3.4, so this only affects profiles that installed it earlier): remove it from the same profile first with `dsh plugin --profile <profile> remove dsh-quarto-book`, then add the scoped package. Keeping both installed registers `writing-quarto` and `designing-theme` twice at the same rank 550.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Installation is scoped to a profile, not to a repository: it only affects the profile that ran `add`. The workspace check still decides whether the two skill names appear: it checks the session `cwd` for a book, and only then are both names selectable. See [docs/plugin-boundaries.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-boundaries.md) for the six cases.
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
| Dependency | Purpose |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| DSH 0.2.x | Host; the plugin registers skills and both tools through `dsh.bundle.patch` |
|
|
43
|
+
| Node.js 22 or newer | Plugin runtime and check scripts |
|
|
44
|
+
| Python 3 | Content, link and naming checks, plus post-render HTML checks |
|
|
45
|
+
| Quarto CLI | Only when `quarto_render_check` actually renders |
|
|
46
|
+
|
|
47
|
+
The published package already contains compiled `lib/`, so installation needs no build step. See [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-layout.md) for the split.
|
|
39
48
|
|
|
40
49
|
## Usage
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
### Writing chapters
|
|
52
|
+
|
|
53
|
+
Load `writing-quarto` in a `type: book` repository and follow the nine steps in `SKILL.md`. Each step opens one same-numbered file in `steps/`; read the same-numbered case in `examples/` only when a signal is unclear; open `quarto/` only for figures, render checks or repository-wide refactors.
|
|
43
54
|
|
|
44
|
-
|
|
55
|
+
The repository's root `README.md` is a description page, not a chapter: it takes only steps 5–8, skips the task skeleton and structure of steps 1–4, has no "common errors" or "self-test questions", and never calls `quarto_render_check`. `README.en.md` is treated the same way.
|
|
45
56
|
|
|
46
|
-
|
|
57
|
+
The plugin has no daemon and does not run skills when a session starts. A skill name in the catalog only means the check passed; only calling `skill`, `quarto_render_check` or `quarto_pass_report` counts as use. A second call in the same session re-reads the skill body, and failed tools are not retried automatically.
|
|
58
|
+
|
|
59
|
+
### Theming
|
|
60
|
+
|
|
61
|
+
Theme assets live in `skills/designing-theme/assets/theme/`. The package copy is authoritative; a book's `theme/` is the render copy. When a copy exists, `designing-theme` edits only that copy. It copies from the package only when the user explicitly asks to install the theme into the book and the target directory does not exist, and it also places `skills/writing-quarto/scripts/answering-disclosure.lua` at `filters/answering-disclosure.lua`. `_quarto.yml` always references the in-book copy, never an npm package or a checkout path.
|
|
62
|
+
|
|
63
|
+
### Checks and rendering
|
|
47
64
|
|
|
48
65
|
Run the content and link checks from the `writing-quarto` skill directory:
|
|
49
66
|
|
|
@@ -54,25 +71,31 @@ python scripts/checking-prose.py --root <book>
|
|
|
54
71
|
python scripts/checking-names.py --root <book>
|
|
55
72
|
```
|
|
56
73
|
|
|
57
|
-
`checking-prose.py` reports only
|
|
74
|
+
`checking-prose.py` reports only mixed Chinese-English problems that can be judged directly; `checking-names.py` is for repository-wide refactors. For everyday chapter work, the first three are enough.
|
|
75
|
+
|
|
76
|
+
Post-render callouts, HTML output and DOM contracts are checked by `quarto_render_check`, which calls the bundled scripts; run `checking-callouts.py`, `checking-output.py` or `checking-dom.py` by hand only when debugging a script. `designing-theme`'s `scripts/checking-layout.py` checks overflow, contrast and page structure on rendered HTML. Neither tool runs those scripts at load time, and neither runs `quarto render`.
|
|
77
|
+
|
|
78
|
+
Call `quarto_pass_report` once at the end of a run; the card is the receipt, and the reply should not repeat it.
|
|
58
79
|
|
|
59
|
-
|
|
80
|
+
### Project skill
|
|
60
81
|
|
|
61
|
-
|
|
82
|
+
A project keeps its own conventions in one skill: `<book>/.agents/skills/quarto-book-project/`, with a template in `templates/quarto-book-project/`. When it exists, both generic skills read its `SKILL.md` first, then the `writing/` files it points to; when it does not exist, they skip it and do not guess.
|
|
83
|
+
|
|
84
|
+
**Do not vendor a same-named skill into the book repository.** DSH picks one skill per name at its rank: `.agents/skills` (rank 200) wins over the plugin (rank 550), so a copy of `writing-quarto` or `designing-theme` inside the book silently replaces the plugin's rules.
|
|
62
85
|
|
|
63
86
|
## Documentation
|
|
64
87
|
|
|
65
88
|
| Document | Contents |
|
|
66
89
|
| --- | --- |
|
|
67
90
|
| [docs/plugin-flow.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-flow.md) | The five layers from install to receipt, file routing and render order |
|
|
68
|
-
| [docs/plugin-boundaries.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-boundaries.md) | The six workspace-
|
|
69
|
-
| [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-layout.md) | Repository
|
|
91
|
+
| [docs/plugin-boundaries.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-boundaries.md) | The six workspace-check cases and their order |
|
|
92
|
+
| [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-layout.md) | Repository layout, package contents, and the Python/Quarto split |
|
|
70
93
|
| [docs/writing-quarto-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/writing-quarto-layout.md) | The writing skill's directory layers |
|
|
71
94
|
| [docs/versioning.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/versioning.md) | Version numbers and release order |
|
|
72
95
|
|
|
73
|
-
##
|
|
96
|
+
## Development
|
|
74
97
|
|
|
75
|
-
The source is TypeScript and the compiled `lib/` is committed
|
|
98
|
+
The source is TypeScript and the compiled `lib/` is committed; the published package loads `lib/` directly and needs no build on install. Link this checkout into the profile you write books with instead of copying skills into the book:
|
|
76
99
|
|
|
77
100
|
```bash
|
|
78
101
|
npm ci
|
|
@@ -81,18 +104,24 @@ npm run check
|
|
|
81
104
|
npm run pack
|
|
82
105
|
```
|
|
83
106
|
|
|
84
|
-
`npm test`
|
|
107
|
+
`npm test` compiles and runs the tool tests; `npm run check` type-checks and validates skill paths; `npm run pack` writes the tarball into `temp/`, which is already in `.gitignore`.
|
|
108
|
+
|
|
109
|
+
Development install:
|
|
85
110
|
|
|
86
111
|
```bash
|
|
87
|
-
dsh plugin --profile web add D
|
|
112
|
+
dsh plugin --profile web add D:\\Github\\dsh-quarto-book
|
|
88
113
|
```
|
|
89
114
|
|
|
90
|
-
`SKILL.md`, `steps/`, `examples/` and `quarto/` are re-read on the next `skill`
|
|
115
|
+
`SKILL.md`, `steps/`, `examples/` and `quarto/` are re-read on the next `skill` call, so rule changes need no npm publish. Theme changes in the package do not reach a book's HTML by themselves: copy the changed files into the book's `theme/` and run `quarto render` in the book root. Do not point `_quarto.yml` at the checkout; that path does not exist on another machine.
|
|
116
|
+
|
|
117
|
+
The plugin ships as a bundle: `package.json` has `dsh.bundle.patch` pointing at `cordis.patch.yml`, and the patch inserts only the `id: quarto-book`, `name: '@chengzhao-dev/dsh-quarto-book'` line. The entry does not import host internals, so it also loads under pnpm's strict dependency layout.
|
|
118
|
+
|
|
119
|
+
The legacy `scripts/embedding-agents.ps1` copies both skill trees into a target repository's `.agents/`, which shadows the plugin at rank 200. Do not use it for new books; run it only to archive a standalone skill tree offline. The command is at the top of the script.
|
|
91
120
|
|
|
92
|
-
|
|
121
|
+
## Issues and contributing
|
|
93
122
|
|
|
94
|
-
|
|
123
|
+
Bugs and suggestions go to [GitHub Issues](https://github.com/chengzhao-dev/dsh-quarto-book/issues). Before sending a change, run `npm test` and `npm run check`; for skill prose, also run `node scripts/checking-skill-links.mjs`.
|
|
95
124
|
|
|
96
|
-
##
|
|
125
|
+
## License
|
|
97
126
|
|
|
98
|
-
MIT.
|
|
127
|
+
MIT. LXGW Bright and LXGW Bright Code in the theme are used under the SIL Open Font License 1.1; the upstream copyright notice and full license are in `skills/designing-theme/assets/theme/assets/fonts/OFL.txt`.
|
package/README.md
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
# dsh-quarto-book
|
|
2
2
|
|
|
3
3
|
[](https://github.com/chengzhao-dev/dsh-quarto-book/actions/workflows/publish.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@chengzhao-dev/dsh-quarto-book)
|
|
4
5
|
|
|
5
6
|
[English](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/README.en.md) | **简体中文**
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- 写 `.qmd`:`writing-quarto` 管章节骨架、结构与中文行文。
|
|
10
|
-
- 改主题:`designing-theme` 管 CSS、字体与 palette。
|
|
11
|
-
- 渲染后检查 HTML:`quarto_render_check` 判一次可发布性,`quarto_pass_report` 出收尾回执。
|
|
8
|
+
在 Quarto Book 仓库里写中文技术章节:`writing-quarto` 管章节骨架与行文,`designing-theme` 管主题样式。两个技能只在 `type: book` 的仓库里出现。渲染后可以用 `quarto_render_check` 判断 HTML 是否可发布,用 `quarto_pass_report` 出一张收尾回执。
|
|
12
9
|
|
|
13
10
|
## 提供什么
|
|
14
11
|
|
|
@@ -17,33 +14,53 @@
|
|
|
17
14
|
| `writing-quarto` | 新建或修改 `content/**/*.qmd`、`index.qmd`、`_quarto.yml`;章节骨架、中文行文、代码与图表、内容检查 | 不改 CSS、字体和颜色 |
|
|
18
15
|
| `designing-theme` | 调整主题的 CSS、SCSS、字体、palette、导航与 Callout 样式 | 不改章节正文 |
|
|
19
16
|
| `quarto_render_check` | 先判断 `output-dir` 是否安全,再按需渲染一次,检查 `_book/` 里的 HTML 是否可发布 | 不改 `.qmd`,不自动修配置,不重复渲染 |
|
|
20
|
-
| `quarto_pass_report` |
|
|
17
|
+
| `quarto_pass_report` | 收尾时把执行结论压成固定行数的回执卡片:技能、模式、改过的文件与步骤、未改项、检查结论 | 不保存到磁盘,不贴章节原文,不据回执改文章 |
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
两个技能从包内 `skills/` 目录发现,按需加载;技能里的相对路径以技能目录为基准:`writing-quarto` 用 `steps/`、`examples/`、`quarto/`、`scripts/`,`designing-theme` 用 `references/`、`knowledge/`、`assets/`、`scripts/`。
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
## 快速开始
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
1. 安装插件:
|
|
27
24
|
|
|
28
|
-
```bash
|
|
29
|
-
dsh plugin --profile web add npm:@chengzhao-dev/dsh-quarto-book@
|
|
30
|
-
```
|
|
25
|
+
```bash
|
|
26
|
+
dsh plugin --profile web add npm:@chengzhao-dev/dsh-quarto-book@latest
|
|
27
|
+
```
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
2. 在书仓库里打开会话。`_quarto.yml` 要有独立一行的 `type: book`,书根至少有一个 `.qmd` 或 `.md` 章节源文件;两个技能名这时才会出现。
|
|
30
|
+
3. 调用技能:写正文用 `writing-quarto`,改主题用 `designing-theme`。
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
`--profile` 换成你实际运行的那个 profile。桌面应用固定跑 `desktop` profile,且该 profile 由应用独占管理,`dsh --profile desktop` 直接启动会被拒绝;安装或升级用 `dsh plugin --profile desktop add <包>`,应用拒绝写入时再走「设置 → 插件 → 添加插件」。需要固定版本时写 `npm:@chengzhao-dev/dsh-quarto-book@0.6.3`,跟 GitHub 标签时写 `github:chengzhao-dev/dsh-quarto-book#v0.6.3`。
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
从旧的无作用域包 `dsh-quarto-book` 升级(该包已随 0.3.4 从 npm 删除,只影响之前装过它的 profile):先在同一个 profile 里 `dsh plugin --profile <profile> remove dsh-quarto-book`,再装新包。两个包同时留着会以相同的 rank 550 各注册一遍 `writing-quarto` 和 `designing-theme`。
|
|
37
35
|
|
|
38
|
-
安装单位是 profile,不是仓库:只影响执行 `add` 的那个 profile
|
|
36
|
+
安装单位是 profile,不是仓库:只影响执行 `add` 的那个 profile。装好之后还要过工作区检查:按会话 `cwd` 判断当前目录是不是一本书,通过后技能名才会出现。检查的六类情形见 [docs/plugin-boundaries.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-boundaries.md)。
|
|
37
|
+
|
|
38
|
+
## 环境要求
|
|
39
|
+
|
|
40
|
+
| 依赖 | 用途 |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| DSH 0.2.x | 宿主;插件按 `dsh.bundle.patch` 注册技能与两个工具 |
|
|
43
|
+
| Node.js 22 及以上 | 运行插件与检查脚本 |
|
|
44
|
+
| Python 3 | 内容、链接、命名检查,以及渲染后的 HTML 检查 |
|
|
45
|
+
| Quarto CLI | 仅 `quarto_render_check` 真正渲染时需要 |
|
|
46
|
+
|
|
47
|
+
发布包已经带编译好的 `lib/`,安装后不需要构建。环境分工见 [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-layout.md)。
|
|
39
48
|
|
|
40
49
|
## 使用
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
### 写章节
|
|
52
|
+
|
|
53
|
+
在 `type: book` 的仓库里加载 `writing-quarto`,按 `SKILL.md` 的九步执行。每一步只打开同号的一个 `steps/` 文件;判不准才读 `examples/` 里同号的案例;要排图、查渲染或全仓重构才打开 `quarto/`。
|
|
54
|
+
|
|
55
|
+
书仓库根目录的 `README.md` 是说明页,不是章节:只走第 5–8 步,不套第 1–4 步的任务与结构骨架,不写「常见错误」「自测问题」,不调 `quarto_render_check`。`README.en.md` 同样处理。
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
插件没有常驻进程,也不会在会话开始时自动执行技能。技能目录里出现名字只说明当前会话过了检查;只有调用 `skill`、`quarto_render_check` 或 `quarto_pass_report` 才算一次使用。同一会话再次调用会重读技能正文,工具失败后不会自动重试。
|
|
45
58
|
|
|
46
|
-
|
|
59
|
+
### 改主题
|
|
60
|
+
|
|
61
|
+
主题资产在 `skills/designing-theme/assets/theme/`,包内是权威来源,书内 `theme/` 是渲染副本。已有副本时 `designing-theme` 只改副本;只有用户明确要求「把插件主题装进这本书」且目标目录不存在,才从包复制,并把 `skills/writing-quarto/scripts/answering-disclosure.lua` 放到书内 `filters/answering-disclosure.lua`。`_quarto.yml` 只引用书内副本,不指向 npm 包或插件检出目录。
|
|
62
|
+
|
|
63
|
+
### 检查与渲染
|
|
47
64
|
|
|
48
65
|
内容与链接检查在 `writing-quarto` 技能目录下运行:
|
|
49
66
|
|
|
@@ -56,21 +73,27 @@ python scripts/checking-names.py --root <book>
|
|
|
56
73
|
|
|
57
74
|
`checking-prose.py` 只报中文混排里能直接判断的问题;`checking-names.py` 只在全仓重构时加跑。日常章节检查跑前三条即可。
|
|
58
75
|
|
|
59
|
-
渲染后的 Callout、HTML 产物与 DOM
|
|
76
|
+
渲染后的 Callout、HTML 产物与 DOM 结构约定由 `quarto_render_check` 调包内脚本完成,不用手跑 `checking-callouts.py`、`checking-output.py` 或 `checking-dom.py`;`designing-theme` 的 `scripts/checking-layout.py` 在渲染后的 HTML 上检查溢出、对比度和页面结构。`apply()` 不在加载时跑这些脚本,也不跑 `quarto render`。
|
|
60
77
|
|
|
61
78
|
一轮结束时调用一次 `quarto_pass_report`,把这次执行的结论压成卡片;卡片就是回执,回复里不再复述。
|
|
62
79
|
|
|
80
|
+
### 项目技能
|
|
81
|
+
|
|
82
|
+
项目只放一份自己的约定技能:`<book>/.agents/skills/quarto-book-project/`,模板见 `templates/quarto-book-project/`。存在时两个通用技能先读它的 `SKILL.md`,再按它指向的 `writing/` 文件读章节表;不存在就跳过,不猜项目约定。
|
|
83
|
+
|
|
84
|
+
**不要把同名技能嵌进书仓库**:DSH 在同一技能层按 rank 取一个,`.agents/skills`(rank 200)优先于插件(rank 550),书里再放 `writing-quarto` 或 `designing-theme` 会让插件正文失效。
|
|
85
|
+
|
|
63
86
|
## 文档
|
|
64
87
|
|
|
65
88
|
| 文档 | 内容 |
|
|
66
89
|
| --- | --- |
|
|
67
90
|
| [docs/plugin-flow.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-flow.md) | 从安装到回执的五层结构、文件分流与渲染顺序 |
|
|
68
|
-
| [docs/plugin-boundaries.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-boundaries.md) |
|
|
91
|
+
| [docs/plugin-boundaries.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-boundaries.md) | 工作区检查的六类情形与判定顺序 |
|
|
69
92
|
| [docs/plugin-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/plugin-layout.md) | 仓库目录、发布包内容与 Python/Quarto 分工 |
|
|
70
93
|
| [docs/writing-quarto-layout.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/writing-quarto-layout.md) | 写作技能的目录分层 |
|
|
71
94
|
| [docs/versioning.md](https://github.com/chengzhao-dev/dsh-quarto-book/blob/main/docs/versioning.md) | 版本号与发布顺序 |
|
|
72
95
|
|
|
73
|
-
##
|
|
96
|
+
## 开发
|
|
74
97
|
|
|
75
98
|
源码用 TypeScript,构建产物 `lib/` 提交进仓库;发布包直接加载 `lib/`,安装后不需要构建。开发时把本仓库链接进写书用的 profile,而不是把技能复制进书:
|
|
76
99
|
|
|
@@ -81,10 +104,12 @@ npm run check
|
|
|
81
104
|
npm run pack
|
|
82
105
|
```
|
|
83
106
|
|
|
84
|
-
`npm test` 会先编译再跑工具测试;`npm run check` 做类型检查与技能路径自检;`npm run pack` 把 tarball 只写进 `temp/`,那个目录已在 `.gitignore`
|
|
107
|
+
`npm test` 会先编译再跑工具测试;`npm run check` 做类型检查与技能路径自检;`npm run pack` 把 tarball 只写进 `temp/`,那个目录已在 `.gitignore` 里。
|
|
108
|
+
|
|
109
|
+
开发安装:
|
|
85
110
|
|
|
86
111
|
```bash
|
|
87
|
-
dsh plugin --profile web add D
|
|
112
|
+
dsh plugin --profile web add D:\\Github\\dsh-quarto-book
|
|
88
113
|
```
|
|
89
114
|
|
|
90
115
|
`SKILL.md`、`steps/`、`examples/`、`quarto/` 在下一次 `skill` 工具调用时重读,改完不用发 npm。包内主题改动不会自动进书的 HTML;要看页面效果,把改过的文件同步到书的 `theme/`,再在书根运行 `quarto render`。不要把 `_quarto.yml` 指到插件检出目录,那条路径换机器就不存在。
|
|
@@ -93,6 +118,10 @@ dsh plugin --profile web add D:\Github\dsh-quarto-book
|
|
|
93
118
|
|
|
94
119
|
旧装机脚本 `scripts/embedding-agents.ps1` 会把两棵技能原样复制进目标仓库的 `.agents/`,按 rank 200 盖住插件;新书不要用它,只有离线归档独立技能树时才执行,命令写在脚本头部。
|
|
95
120
|
|
|
121
|
+
## 问题与贡献
|
|
122
|
+
|
|
123
|
+
问题与建议走 [GitHub Issues](https://github.com/chengzhao-dev/dsh-quarto-book/issues)。提交改动前先运行 `npm test` 与 `npm run check`;涉及技能正文时,同时跑 `node scripts/checking-skill-links.mjs`。
|
|
124
|
+
|
|
96
125
|
## 许可
|
|
97
126
|
|
|
98
127
|
MIT。主题内的 LXGW Bright 与 LXGW Bright Code 按 SIL Open Font License 1.1 使用;上游版权声明与许可全文在 `skills/designing-theme/assets/theme/assets/fonts/OFL.txt`。
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `quarto_render_check`:先判断渲染输出目录是否安全,再在 120 秒内跑一次
|
|
2
|
-
// `quarto render`,最后检查产出的 HTML
|
|
2
|
+
// `quarto render`,最后检查产出的 HTML 是否可发布。失败只报告,不自动重新运行。
|
|
3
3
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
4
4
|
import { readFile, readdir } from 'node:fs/promises';
|
|
5
5
|
import path from 'node:path';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chengzhao-dev/dsh-quarto-book",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "润色中文技术章节,检查 Book 结构与中英混排,并维护一套统一、可读的阅读主题。 · Polish Chinese technical chapters, check book structure and mixed Chinese-English prose, and maintain a consistent, readable theme.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"README.md",
|
|
20
20
|
"README.en.md",
|
|
21
21
|
"LICENSE",
|
|
22
|
-
"templates"
|
|
22
|
+
"templates",
|
|
23
|
+
"!**/__pycache__",
|
|
24
|
+
"!**/__pycache__/**",
|
|
25
|
+
"!**/*.pyc"
|
|
23
26
|
],
|
|
24
27
|
"engines": {
|
|
25
28
|
"node": ">=22",
|
|
Binary file
|
|
Binary file
|
|
@@ -105,14 +105,13 @@ body {
|
|
|
105
105
|
color: var(--body-color) !important;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
/* ----------
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
/* ---------- 类图:预算优先,容器只做兜底 ----------
|
|
109
|
+
类图先按 writing-quarto 技能 quarto/mermaid.md 的内容预算删到栏宽以内;
|
|
110
|
+
这里只保证高度自适应并居中,内容超宽时由容器兜底。 */
|
|
111
111
|
#quarto-document-content .class-diagram .cell-output-display figure.figure {
|
|
112
112
|
overflow-x: auto;
|
|
113
113
|
}
|
|
114
|
-
body.program-map #quarto-document-content .cell-output-display figure.figure svg,
|
|
115
114
|
#quarto-document-content .class-diagram .cell-output-display figure.figure svg {
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
height: auto;
|
|
116
|
+
margin-inline: auto;
|
|
118
117
|
}
|
|
@@ -65,7 +65,7 @@ Bright Code 在 16px 下每个 ASCII 字符前进 8px;现在代码正文 15px
|
|
|
65
65
|
|
|
66
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
67
|
|
|
68
|
-
第三套是读者自己的「山光」四时色板(`palettes/hill-light`,取自 `D:\Github\hill-light\hill-light-theme`
|
|
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` 类;打印时夜月回落到晓雾令牌,纸面不出深底。
|
|
69
69
|
|
|
70
70
|
## 抬色记录与保留的低对比项
|
|
71
71
|
|
|
@@ -40,11 +40,11 @@
|
|
|
40
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,不适合中西文都自托管的站点。
|
|
41
41
|
|
|
42
42
|
- 文件与预算:`assets/theme/assets/fonts/` 每字体一个 `*-common.woff2`(共 2 个),单页合计 ≤ 1.6 MB、≤ 5 个文件。
|
|
43
|
-
- 子集:沿用常用字表并覆盖全书正文与终端输出;生成方式 `pyftsubset --flavor=woff2 --no-hinting`。改结果文案或新增字符后,用 fontTools 读 woff2 cmap 复核(起因:子集共用字符表漏「胜」,结果行末字落到宋体);`checking-layout.py` 的覆盖断言在未声明 unicode-range 时直接读 cmap
|
|
43
|
+
- 子集:沿用常用字表并覆盖全书正文与终端输出;生成方式 `pyftsubset --flavor=woff2 --no-hinting`。改结果文案或新增字符后,用 fontTools 读 woff2 cmap 复核(起因:子集共用字符表漏「胜」,结果行末字落到宋体);`checking-layout.py` 的覆盖断言在未声明 unicode-range 时直接读 cmap。新增字符时,按同版本上游 TTF(Bright 5.528、Bright Code 2.922)保留现 cmap 并入新码位后重建,输出到插件与书内两份;跑页面矩阵时用 `NODE_PATH` 指向插件的 `node_modules`。
|
|
44
44
|
- 覆盖范围不只汉字:西文标点、数学/箭头、制表符、几何图形与全角形式(U+FF01–FF5E)同在断言内(`GLYPH_RANGES`)。漏一个字不会被发现,却会静默回落到系统 CJK 字体,按 0.5em 的中线画出——正文 `+` 墨迹在 0.23em,「++」会显得浮在汉字上方。表情符号(≥U+1F000、U+2600–U+27BF)按设计走系统 emoji,不在断言内。
|
|
45
45
|
- 不逐符号位移:Bright 的数字、括号、`× ÷ = +` 共用同一条数学轴(+ 中心 0.23em,汉字 0.357em)。只抬 `++` 会脱离同行的符号,所以 `.plus-align` 这类 `translateY` 已删除;对齐问题只在字形缺失时补码位。
|
|
46
46
|
- 同步点:改字体须同步 SCSS、tokens、fonts、OFL、资产与 `checking-layout.py`;Mermaid 的 `%%{init}%%` 与坐标图脚本的 `FONT_FAMILY` 用同栈短版(`LXGW Bright Medium, system-ui, sans-serif`),保证测量与渲染一致。
|
|
47
|
-
- 栈尾 CJK
|
|
47
|
+
- 栈尾 CJK 系统字体后备(PingFang SC、Microsoft YaHei、Noto Sans CJK SC、Source Han Sans SC)保留,缺字时落系统黑体而不是浏览器默认宋体。
|
|
48
48
|
- 不采用 Inter、思源黑体、JetBrains Mono、Cascadia、Iosevka、Inconsolata;Roboto/Segoe UI 不放进 `assets/theme/assets/fonts/`(OFL 政策)。
|
|
49
49
|
|
|
50
50
|
## 字号、行长与页面尺度(定尺度)
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
- **列表与折叠**:marker 用 `--text-secondary`,折叠三角用正文色;答案盒子只用上下 hairline,不做卡片。
|
|
80
80
|
- **首页目录**:不是卡片;每行一条顶线、透明底、无圆角,一行最多两列;单张卡占满整行,序号 `01` 起、动作链接靠右下,窄屏动作移到提要下方;hover 只把顶线换成 `--accent`。
|
|
81
81
|
- **章节翻页**:一条顶线 + 左右两个文字链接,不用边框卡片;箭头用 `<` / `>`,hover 才转 `--accent`,下一页右对齐。箭头用字符而不用 SVG 是量过的:Bright 的 `<` `>` 墨迹中心在 0.23em,与同行西文同一轴,没有面包屑 `>` 那种偏高,换 SVG 反而要另配基线。
|
|
82
|
-
- **章节线**:标题不画线。全书只有一种横线——通栏 1px `--card-border` 发丝线,只出现在顶栏底边、引用块上下边、表格 booktabs、首页目录每行顶线、翻页顶线、页脚顶线、答案折叠线;`h2::after` 的 2.25rem 短发丝线已删除(连同首页 `.feature-grid` 例外),章节节奏只靠 H2 的 `margin-top: 3.25rem`
|
|
82
|
+
- **章节线**:标题不画线。全书只有一种横线——通栏 1px `--card-border` 发丝线,只出现在顶栏底边、引用块上下边、表格 booktabs、首页目录每行顶线、翻页顶线、页脚顶线、答案折叠线;`h2::after` 的 2.25rem 短发丝线已删除(连同首页 `.feature-grid` 例外),章节节奏只靠 H2 的 `margin-top: 3.25rem` 与字号台阶。约定改动时同步本节与 `css/base.css`。
|
|
83
83
|
- **引用块**:上下各一条 1px `--card-border` 横线、正文色、无底色、无左右竖条;与 Callout 的 2px 左色条区分开(后者是类型标记,不是分隔线)。
|
|
84
84
|
- **表格**:`display: block` + 块内横向滚动承载宽表;Chrome 的表格修复会把同一块里的 `thead`/`tbody` 包进一个匿名表,所以列宽仍逐列对齐(1280 与 390 实测一致),不需要 JS 量列宽。表题走 `caption-side: top`、左对齐、14px `--text-secondary`;`table-striped` 压平成与普通行同底。
|
|
85
85
|
- **脚注**:区块顶部一条 1px `--card-border`、`margin-top: 3rem`、14px / lh 1.7、`--text-secondary`;回跳箭头随正文链接色。
|
|
@@ -112,7 +112,7 @@ Quarto Book 三栏;编译默认色板 `palettes/flexoki`(Flexoki Light / Dar
|
|
|
112
112
|
|
|
113
113
|
## 主题结构与装配
|
|
114
114
|
|
|
115
|
-
官方字段见 Quarto HTML format reference
|
|
115
|
+
官方字段见 Quarto HTML format reference。下列路径与装配顺序是本项目约定。
|
|
116
116
|
|
|
117
117
|
### 文件职责
|
|
118
118
|
|
|
@@ -162,7 +162,7 @@ Solarized 是运行时层,不进 `_quarto.yml` 的 theme/highlight-style:读
|
|
|
162
162
|
3. `callouts.css` 加 `.callout.callout-<name>`。
|
|
163
163
|
4. 新语义写入本节令牌索引。
|
|
164
164
|
|
|
165
|
-
###
|
|
165
|
+
### 校验与高亮约定
|
|
166
166
|
|
|
167
167
|
- `checking-layout.py` 校验令牌与布局;发布用 `1280/768/390/360` 明暗与触屏、窄屏浮层。
|
|
168
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)。
|
|
@@ -645,8 +645,52 @@ def read_font_cmap(path):
|
|
|
645
645
|
return set(cmap)
|
|
646
646
|
|
|
647
647
|
|
|
648
|
+
def qmd_font_chunks(path):
|
|
649
|
+
"""Split a qmd into prose text and code text for font coverage checks."""
|
|
650
|
+
text = path.read_text(encoding="utf-8", errors="ignore")
|
|
651
|
+
text = re.sub(r"\A---\s*\n.*?\n---\s*\n", "", text, count=1, flags=re.S)
|
|
652
|
+
text = re.sub(r"<!--.*?-->", "", text, flags=re.S)
|
|
653
|
+
prose_lines = []
|
|
654
|
+
prose_chunks = []
|
|
655
|
+
code_chunks = []
|
|
656
|
+
fence = None
|
|
657
|
+
fence_is_mermaid = False
|
|
658
|
+
buffer = []
|
|
659
|
+
for line in text.splitlines():
|
|
660
|
+
if fence is not None:
|
|
661
|
+
if line.strip().startswith(fence):
|
|
662
|
+
chunk = "\n".join(buffer)
|
|
663
|
+
if fence_is_mermaid:
|
|
664
|
+
prose_chunks.append(chunk)
|
|
665
|
+
else:
|
|
666
|
+
code_chunks.append(chunk)
|
|
667
|
+
fence = None
|
|
668
|
+
buffer = []
|
|
669
|
+
else:
|
|
670
|
+
buffer.append(line)
|
|
671
|
+
continue
|
|
672
|
+
match = re.match(r"^\s*(`{3,}|~{3,})(.*)$", line)
|
|
673
|
+
if match:
|
|
674
|
+
fence = match.group(1)
|
|
675
|
+
fence_is_mermaid = "mermaid" in match.group(2)
|
|
676
|
+
buffer = []
|
|
677
|
+
else:
|
|
678
|
+
prose_lines.append(line)
|
|
679
|
+
if fence is not None:
|
|
680
|
+
chunk = "\n".join(buffer)
|
|
681
|
+
(prose_chunks if fence_is_mermaid else code_chunks).append(chunk)
|
|
682
|
+
prose = "\n".join(prose_lines)
|
|
683
|
+
prose = re.sub(r"\]\([^)]*\)", "]", prose)
|
|
684
|
+
prose = re.sub(r"^\s*\[[^\]]+\]:\s*\S+.*$", "", prose, flags=re.M)
|
|
685
|
+
prose = re.sub(r"https?://\S+", "", prose)
|
|
686
|
+
prose = re.sub(r"<[^>]+>", "", prose)
|
|
687
|
+
inline_code = re.findall(r"`([^`\n]+)`", prose)
|
|
688
|
+
prose = re.sub(r"`[^`\n]+`", "", prose)
|
|
689
|
+
return [prose, *prose_chunks], [*inline_code, *code_chunks]
|
|
690
|
+
|
|
691
|
+
|
|
648
692
|
def check_font_coverage(book_dir):
|
|
649
|
-
"""Check Chinese coverage for
|
|
693
|
+
"""Check Chinese coverage for prose and code in qmd sources separately.
|
|
650
694
|
|
|
651
695
|
声明了 unicode-range 的 face 按声明区间判定。未声明时用 fontTools
|
|
652
696
|
读取字体文件的真实 cmap 判定。起因:子集字符表漏字,正文落到系统宋体。
|
|
@@ -676,15 +720,11 @@ def check_font_coverage(book_dir):
|
|
|
676
720
|
missing = {family: set() for family in FONT_FAMILIES}
|
|
677
721
|
if not any(coverage.values()):
|
|
678
722
|
return coverage, missing
|
|
679
|
-
for
|
|
680
|
-
|
|
681
|
-
page_parser = VisibleTextParser()
|
|
682
|
-
page_parser.feed(html_text)
|
|
683
|
-
code_parser = VisibleTextParser(code_only=True)
|
|
684
|
-
code_parser.feed(html_text)
|
|
723
|
+
for qmd_path in sorted(book_dir.rglob("*.qmd")):
|
|
724
|
+
prose_chunks, code_chunks = qmd_font_chunks(qmd_path)
|
|
685
725
|
for family, chunks in (
|
|
686
|
-
("LXGW Bright Medium",
|
|
687
|
-
("LXGW Bright Code",
|
|
726
|
+
("LXGW Bright Medium", prose_chunks),
|
|
727
|
+
("LXGW Bright Code", code_chunks),
|
|
688
728
|
):
|
|
689
729
|
for chunk in chunks:
|
|
690
730
|
for char in chunk:
|
|
@@ -27,10 +27,10 @@ metadata:
|
|
|
27
27
|
## 九步
|
|
28
28
|
|
|
29
29
|
1. 定任务:写出读者做完能完成的那件事,再列这一章要覆盖的任务。规则在 `steps/01-task.md`。
|
|
30
|
-
2.
|
|
30
|
+
2. 定结构:排页面骨架、二级标题和篇幅预算,只定删留、标题与章题对齐。规则在 `steps/02-structure.md`。
|
|
31
31
|
3. 排列内容块:导语、围栏、收束与 Callout 的次序,一个围栏只放正在讲的那一块。规则在 `steps/03-blocks.md`。
|
|
32
32
|
4. 定段落:一段一个对象,段间衔接落在话题切换处。规则在 `steps/04-paragraphs.md`。
|
|
33
|
-
5.
|
|
33
|
+
5. 定句子:主语选执行者,对象先行,一句一动作。规则在 `steps/05-sentences.md`。
|
|
34
34
|
6. 定用词:统一术语、主动语态和语气。规则在 `steps/06-wording.md`。
|
|
35
35
|
7. 定版式:标点、中英混排、列表和加粗。规则在 `steps/07-layout.md`。
|
|
36
36
|
8. 回读并退回:按现象判断属于哪一步,退回那一步改。规则在 `steps/08-reread.md`。
|