feat: IMAP mail sync with thread-to-contact matching (PRD §6.1)
Real IMAP connection via imapflow library: - Connects to IMAP server (IMAPFlow, TLS on port 993) - Fetches recent messages (configurable limit, default 20) - Extracts: from, fromEmail, subject, date, snippet (200 chars) - Thread-to-contact matching (PRD §6.1): 1. Match sender email against persons table 2. If no person match, extract domain and match against company.website 3. Returns matchedCompany + matchedPerson for each email - Audit-logged (action: crm.mailsync:imap) - Zod validated (host, port, user, password, folder, limit) - 502 on IMAP connection failure with detail - 400 on validation failure Tested: invalid creds → 502 'IMAP connection failed', missing host → 400
This commit is contained in:
1 parent
7acc0c5451
commit
e45b68bb8b
1089 files changed
+260614
No files matched your search
@@ -0,0 +1,349 @@
|
||||
# 标题断句 与 一般断行 Title Line Breaking & Word Wrapping
|
||||
|
||||
中文排版里最容易被忽略的一组规则。**正文断行和标题断行逻辑完全相反**——正文按字、标题按词。这个差异不知道,就会把"我外交部强烈谴责伊拉克"和"大使馆被炸事件"在标题里硬切两行。
|
||||
|
||||
## 一、核心原则
|
||||
|
||||
| 文本类型 | 断行逻辑 | 原因 |
|
||||
|---|---|---|
|
||||
| **正文** | 按字断,不按词 | 汉语双音节词约占 60%,按词断会形成锯齿状右缘,方块字硕大无法形成西文那样的"波浪状" |
|
||||
| **标题** | 必须按词断 | 字数少、视觉占比大,词被切开会产生歧义和阅读阻塞 |
|
||||
| **诗词** | 按句断(每句独占一行或按对齐排列) | 节奏感优先 |
|
||||
| **目录、列表** | 按条目断(必要时换行用次行缩进) | 凸排(hanging)保持检索性 |
|
||||
|
||||
## 二、标题断行规则
|
||||
|
||||
### 1. 不可在词中间断开
|
||||
|
||||
绝对不可拆的"词单位":
|
||||
- **专有名词**:人名(毛泽东 / 习近平 / 苏炳添)、地名(北京 / 哈尔滨 / 上海浦东)、机构名(外交部 / 中央电视台)、品牌(华为 / 字节跳动)
|
||||
- **术语**:人工智能、深度学习、量子纠缠、新冠肺炎
|
||||
- **数字 + 单位**:3 公斤、500 万、第 5 章
|
||||
- **数字串**:2024 年、100 元
|
||||
- **书名 / 影片名 / 歌名**:《静夜思》、《流浪地球 2》
|
||||
- **成语 / 熟语**:守株待兔、海纳百川(4 字成语整体不拆)
|
||||
|
||||
### 2. 虚词位禁忌
|
||||
|
||||
| 字 / 词 | 禁忌位置 | 原因 |
|
||||
|---|---|---|
|
||||
| **的、地、得、之、所** | **不入行首** | 修饰关系断了 |
|
||||
| **和、与、及、或、跟、同** | **不入行末** | 并列关系悬空 |
|
||||
| **是、为、乃** | 不入行首 | 系动词需有主语 |
|
||||
| **在、于、对、向、从** | 不入行末 | 介词需带宾语 |
|
||||
| **了、着、过** | 不入行首 | 助词依附前字 |
|
||||
| **吗、呢、吧、啊、哦** | 不入行首(语气词通常)| 同上 |
|
||||
|
||||
### 3. 标题反例与修正
|
||||
|
||||
❌ **反例 1**(歧义):
|
||||
```
|
||||
我外交部强烈谴责伊拉克
|
||||
大使馆被炸事件
|
||||
```
|
||||
读者可能误解为"伊拉克大使馆被炸"。
|
||||
|
||||
✅ **修正**:
|
||||
```
|
||||
我外交部强烈谴责
|
||||
伊拉克大使馆被炸事件
|
||||
```
|
||||
|
||||
❌ **反例 2**(词中断):
|
||||
```
|
||||
苹果发布全新人工智
|
||||
能芯片 M5
|
||||
```
|
||||
|
||||
✅ **修正**:
|
||||
```
|
||||
苹果发布全新
|
||||
人工智能芯片 M5
|
||||
```
|
||||
|
||||
❌ **反例 3**(虚词位):
|
||||
```
|
||||
中国队战胜了美国队和
|
||||
日本队
|
||||
```
|
||||
|
||||
✅ **修正**("和"不入行末):
|
||||
```
|
||||
中国队战胜了
|
||||
美国队和日本队
|
||||
```
|
||||
|
||||
### 4. 标题占行规则(铅排经验值)
|
||||
|
||||
标题必须占整数倍正文行高,否则跨栏对不齐。
|
||||
|
||||
| 标题层级 | 占行(含上下空白) | 典型字号(正文 9pt 时) |
|
||||
|---|---|---|
|
||||
| 大标题(章首) | 4–5 行 | 18–24pt |
|
||||
| 中标题(节首) | 2–3 行 | 12–15pt |
|
||||
| 小标题 | 1–2 行 | 10–12pt |
|
||||
| 双行标题(主 + 副)| 3 行 | 主 12pt + 副 9pt |
|
||||
| 同行标题(小节首)| 1 行(接续正文)| 9pt 加粗 |
|
||||
|
||||
**关键原则**:标题字号 + 上下空白 = 正文行高 × N。**否则后面所有正文都对不齐基线**。
|
||||
|
||||
### 5. 标题在页面中的位置
|
||||
|
||||
- **大标题(章首)**:必出现在**正面页**
|
||||
- 横排左翻书 → 右页(奇数页)
|
||||
- 直排右翻书 → 左页(奇数页)
|
||||
- 若大标题前一章末页停在正面页 → 反面页留空白("双白页"是必要的,不要为省纸打破)
|
||||
- **换页 vs 单页起**:
|
||||
- 换页:从新页开始,不论奇偶(中小标题用)
|
||||
- 单页起:必从正面页开始(大标题用)
|
||||
- **中小标题孤行处理**:若中小标题落到页末且后续正文容不下,**整个标题换到下一页开头**
|
||||
|
||||
### 6. 标题对齐方式
|
||||
|
||||
| 排版方向 | 大标题对齐 | 小标题对齐 |
|
||||
|---|---|---|
|
||||
| 横排 | 多居中 | 多左对齐 / 段首空格 |
|
||||
| 直排 | 对行首(顶天) / 下沉(如下字常用 2 字位)| 同 |
|
||||
|
||||
**直排标题"下字 2 字位置"**:直排时标题从天头空 2 字开始,避免顶天造成压抑。
|
||||
|
||||
### 7. 同行标题
|
||||
|
||||
小节标题不换行,直接接续正文。处理:
|
||||
|
||||
```
|
||||
四、本章小结 本章我们讨论了……
|
||||
↑
|
||||
1 字空白
|
||||
```
|
||||
|
||||
- 标题与正文之间空 1 字位置
|
||||
- 若标题字号非整数倍,调整空白让正文头尾对齐
|
||||
|
||||
## 三、CSS / HTML 实现标题断行
|
||||
|
||||
### 方法 1:手工 `<br>` 控制断点(最稳)
|
||||
```html
|
||||
<h1>
|
||||
我外交部强烈谴责<br>
|
||||
伊拉克大使馆被炸事件
|
||||
</h1>
|
||||
```
|
||||
|
||||
### 方法 2:`<wbr>` 提示断点(允许在此换行)
|
||||
```html
|
||||
<h1>苹果发布全新<wbr>人工智能芯片 M5</h1>
|
||||
```
|
||||
|
||||
### 方法 3:U+2060 WORD JOINER(禁止在此换行)
|
||||
```html
|
||||
<h1>第⁠5⁠章 深度学习</h1>
|
||||
```
|
||||
注意:**不要**用 `‍`(U+200D ZERO WIDTH JOINER)—— 那是给阿拉伯文/天城文连写用的,对中文断行无效。
|
||||
|
||||
### 方法 4:CSS `text-wrap: balance`(现代浏览器)
|
||||
```css
|
||||
h1, h2, h3 {
|
||||
text-wrap: balance; /* 让多行标题各行字数尽量均衡 */
|
||||
}
|
||||
```
|
||||
|
||||
### 方法 5:响应式断点(不同屏宽换不同断点)
|
||||
```html
|
||||
<h1>
|
||||
我外交部强烈谴责<br class="md-only">
|
||||
<wbr>伊拉克大使馆被炸事件
|
||||
</h1>
|
||||
<style>
|
||||
@media (min-width: 768px) {
|
||||
.md-only { display: inline; }
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 四、正文断行规则
|
||||
|
||||
正文按字断,但 6 类位置**不能拆**(不可分离禁则):
|
||||
|
||||
### 1. 阿拉伯数字内部不拆
|
||||
- ❌ `100`<br>`0 元`
|
||||
- ✅ 整体到下一行
|
||||
|
||||
### 2. 数字 + 单位不拆
|
||||
- 数字 + `%`、`‰`、`°`、`℃`、`℉` 不拆
|
||||
- 数字 + `±`、`+`、`−` 之前的符号不拆
|
||||
- 数字 + 货币 `¥`、`$`、`€`、`£` 不拆
|
||||
|
||||
### 3. 上下标 / 注释记号 + 被标记词不拆
|
||||
- ❌ `m`<br>`²`
|
||||
- ❌ 苹果<sup>1</sup> <br> 公司
|
||||
- ✅ 注释上标紧贴前一个字
|
||||
|
||||
### 4. 破折号 / 省略号不可拆开
|
||||
- 破折号 `——`(2 字宽)不可在中间断开
|
||||
- 省略号 `……`(2 字宽)不可在中间断开
|
||||
- 连续多个破折号 `————` 允许在每一组之间拆
|
||||
|
||||
### 5. 西文单词按 hyphenation 断
|
||||
- 横排中混排的西文单词遇行尾按西文连字符规则断词
|
||||
- 直排中旋转 90° 的西文单词除连字符外不拆
|
||||
|
||||
### 6. URL / 邮件地址特殊处理
|
||||
- 建议在 `@`、`/`、`?` 等符号处断行
|
||||
- **不得加连字符**(连字符会被误解为 URL 的一部分)
|
||||
- **不改大小写**
|
||||
- CSS:`overflow-wrap: anywhere`(针对长 URL)
|
||||
|
||||
### CSS 实现"不可分离禁则"
|
||||
|
||||
```css
|
||||
.body-text {
|
||||
word-break: keep-all; /* 不在词中间断 */
|
||||
overflow-wrap: break-word; /* 但允许长 URL 换行 */
|
||||
line-break: strict; /* 严格避头尾 */
|
||||
text-spacing-trim: space-all; /* 标点空间挤压 */
|
||||
hanging-punctuation: allow-end; /* 末行标点悬挂 */
|
||||
}
|
||||
|
||||
/* 关键:不要这样写 */
|
||||
.bad {
|
||||
word-break: break-all; /* ❌ 会让中文按字硬断,避头尾全失效 */
|
||||
}
|
||||
|
||||
/* 不可断的小组:数字+单位、上下标 */
|
||||
.unit, .superscript-group {
|
||||
white-space: nowrap; /* 整组不换行 */
|
||||
}
|
||||
```
|
||||
|
||||
### 不可断小组的 HTML 标记
|
||||
|
||||
```html
|
||||
<!-- 数字+单位 -->
|
||||
温度 <span class="unit">25 ℃</span>
|
||||
价格 <span class="unit">¥ 999.99</span>
|
||||
|
||||
<!-- 上下标 -->
|
||||
面积 <span class="superscript-group">10 m<sup>2</sup></span>
|
||||
|
||||
<!-- 注释记号 -->
|
||||
苹果公司<sup class="superscript-group">①</sup>
|
||||
|
||||
<!-- 用 U+2060 也可 -->
|
||||
温度 25⁠℃
|
||||
```
|
||||
|
||||
## 五、孤行孤字(Widow & Orphan)
|
||||
|
||||
排版的"末页综合症":段末单字、页首单行。**不修就是失败。**
|
||||
|
||||
### 1. 孤字不成行(Orphan)
|
||||
|
||||
**症状**:段落最后一行只有 1 个字 + 1 个标点。
|
||||
|
||||
**3 种救济**(按优先级):
|
||||
|
||||
#### 救济 A:挤进上行(首选)
|
||||
- 通过标点宽度调整:把上一行的标点全部从全宽改为半宽,腾出空间
|
||||
- 通过中西间距调整:把中西混排的 1/4 em 间距压到 1/8 em
|
||||
- 通过字距均压:上一行字距压缩 1/24 em
|
||||
|
||||
#### 救济 B:删字让孤字回前行
|
||||
- 与作者商议删去 1–2 个字
|
||||
- 修改句法("非常" → "很")
|
||||
|
||||
#### 救济 C:加字让末行≥3 字
|
||||
- 与作者商议补 1 字让末行不再"孤"
|
||||
- 加补缀词("了"、"的"、"则")
|
||||
|
||||
#### 救济 D(次选):均排末行
|
||||
- 让末行 1 个字均排到整个版心宽度
|
||||
- 适用于诗歌、对联,**不适用于现代文**(看着别扭)
|
||||
|
||||
### 2. 孤行不成页(Widow)
|
||||
|
||||
**症状**:页首是前段的最后一行(1 行 + 段间空白)。
|
||||
|
||||
**4 种救济**(按优先级):
|
||||
|
||||
#### 救济 A:孤行回前页(突出版心)
|
||||
- 让孤行超出地脚版心 1 行,与前段连在一起
|
||||
- 此页地脚临时缩小 1 行(在不严格场合允许)
|
||||
|
||||
#### 救济 B:前页末段取 1 行
|
||||
- 修改前段,让前段在前页最后一行结束自然停顿
|
||||
- 让新段从本页开始(最自然)
|
||||
|
||||
#### 救济 C:删字
|
||||
- 删本段开头 1 行字数,让孤行不再孤
|
||||
|
||||
#### 救济 D:加字
|
||||
- 在前段补 1 行字数
|
||||
|
||||
### 3. CSS 实现
|
||||
|
||||
```css
|
||||
p {
|
||||
orphans: 2; /* 段末至少留 2 行(避免 1 字孤悬)*/
|
||||
widows: 2; /* 段首至少留 2 行(避免 1 行孤悬)*/
|
||||
}
|
||||
|
||||
/* 段不要被分页符切断 */
|
||||
h1, h2, h3 {
|
||||
page-break-after: avoid; /* 标题后不分页 */
|
||||
break-after: avoid-page; /* 同上,现代写法 */
|
||||
}
|
||||
|
||||
img, figure {
|
||||
page-break-inside: avoid; /* 图片不被切断 */
|
||||
break-inside: avoid;
|
||||
}
|
||||
```
|
||||
|
||||
## 六、断行控制工具汇总
|
||||
|
||||
| 工具 | 控制粒度 | 用法 | 平台 |
|
||||
|---|---|---|---|
|
||||
| `<br>` | 强制换行 | HTML | 所有 |
|
||||
| `<wbr>` | 软断点(允许在此换行) | HTML5 | 现代浏览器 |
|
||||
| `⁠` (U+2060 WJ) | 禁止在此换行 | HTML 字符 | 现代浏览器 |
|
||||
| ` ` | 不可换行空格 | HTML 字符 | 所有 |
|
||||
| `white-space: nowrap` | 整段不换行 | CSS | 所有 |
|
||||
| `word-break: keep-all` | 单词内不断(不要 `break-all`) | CSS | 所有现代 |
|
||||
| `overflow-wrap: break-word` | 超长词允许换行 | CSS | 现代浏览器 |
|
||||
| `line-break: strict` | 严格避头尾 | CSS | 现代浏览器 |
|
||||
| `text-wrap: balance` | 多行均衡 | CSS | 现代浏览器(2024+) |
|
||||
| `hyphens: auto` | 西文自动连字符 | CSS | 现代浏览器 |
|
||||
|
||||
## 七、InDesign / Word 中的断行设置
|
||||
|
||||
### InDesign
|
||||
1. **关闭"连数字"**(默认开启会把"以防万一"中的"万一"误判数字):
|
||||
- 不打开任何文档 → 段落面板选项 → 关闭"连数字" → 影响所有新文档
|
||||
2. **选用 Adobe CJK 单行书写器**(不是段落书写器)
|
||||
- 段落书写器会把单行字距调整污染相邻行
|
||||
3. **避头尾设置**:选"简体中文避头尾",避头尾间断类型选"先推入"或"确定调整量优先级"
|
||||
4. **段落面板"禁止断字"**勾选(默认开),破折号才不被拆
|
||||
|
||||
### Word
|
||||
1. 段落对话框 → 中文版式
|
||||
2. 勾选"允许标点溢出边界"
|
||||
3. 勾选"按中文习惯控制首尾字符"
|
||||
4. "首尾字符"选"标准"或"严格"
|
||||
5. **注意**:Word 默认中文"后置标点"不包含 `U+2014`,破折号需要手动加入"自定义后置标点"
|
||||
|
||||
## 八、检查清单(断行相关)
|
||||
|
||||
排印完成前必过:
|
||||
|
||||
- [ ] 所有标题是否按词断、不在词中间硬断?
|
||||
- [ ] 标题中"的"是否在行首?"和/与"是否在行末?
|
||||
- [ ] 标题占行是否为正文行高整数倍?
|
||||
- [ ] 大标题是否在正面页(横右页 / 直左页)?
|
||||
- [ ] 数字 + 单位是否整组不分行?(用 `<span class="unit">` 或 `⁠`)
|
||||
- [ ] 破折号、省略号是否未被中间拆开?
|
||||
- [ ] 注释上标是否与被标记词紧贴?
|
||||
- [ ] 段末是否有"孤字 + 标点"?
|
||||
- [ ] 页首是否有"孤行"?
|
||||
- [ ] URL / 邮箱是否在合理位置断(不加连字符)?
|
||||
- [ ] CSS 是否用 `word-break: keep-all` 而不是 `break-all`?
|
||||
Reference in new issue
Block a user