Files
Z User e45b68bb8b 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
2026-10-27 22:50:50 +00:00

414 lines
16 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 标点全规则 Punctuation:风格 / 挤压 / 避头尾 / 破折号
中文排版的"暗物质"。占文本面积 5%–15%,决定 95% 的"专业感"。本文按 6 个主题展开:4 种标点风格、加法/减法模式、4 级避头尾、行内挤压/拉伸优先级、破折号专题、Unicode 码位速查。
## 一、4 种标点风格
不要混用。一个项目锁定一种风格。
### 1. 全角式(Full-width)
- 所有标点占 1 个汉字宽
- 出现场景:默认网页排版(引擎不调)、《普列汉诺夫美学论文选》等老派出版
- 优点:纵横对齐严格
- 缺点:标点连用形成"白窟窿"(` "。( ` 三符 ≈ 3 格空白)
- CSS:默认行为(无需特别处理)
### 2. 半角式(Half-width)
- 所有标点占 0.5 个汉字宽
- 出现场景:辞典(《汉语大字典》节约空间)、苹果中国官网 2018 年(用 WebFont SF Pro SC)
- 优点:紧凑,西文混排自然
- 缺点:句末停顿感弱,影响阅读节奏
- CSS:`font-feature-settings: "halt" 1;` 或换用半宽字体
### 3. 开明式(Kaiming-style,大陆纸媒主流)
- **句末标点全宽**:`。 ? !`(句号、问号、叹号)
- **句内标点半宽**:`, 、 ; :`(逗号、顿号、分号、冒号)
- 出现场景:大陆纸媒、方正飞腾默认、绝大多数大陆图书
- **推荐用于大陆现代横排正文**
- CSS:手动控制或用 InDesign 标点挤压预设
### 4. 居中式(Centered,港台主流)
- 所有标点全宽 + 字面正中
- 同时适应横排和直排(标点位置一致)
- 出现场景:港台几乎所有出版物、传统书法集
- 优点:方向无关、对纵横对齐友好
- 缺点:横排时"。"看着像浮在中间
- CSS:港台地区字体(如华康、文鼎)自带这种字面分布
### 选择决策表
| 项目类型 | 推荐风格 | 备注 |
|---|---|---|
| 大陆现代图书 / 杂志 / 报刊 | 开明式 | 主流选择 |
| 大陆学术论文 / 招股书 / 公文 | 开明式 | 严肃 |
| 港台繁体书籍 | 居中式 | 民国延续 |
| 字典 / 辞海 / 工具书 | 半角式 | 节约空间 |
| 网页正文(无引擎支持时) | 全角式(被迫) | 加 `text-spacing-trim` 可改善 |
| 现代网页 / App(有引擎) | 开明式 + `text-spacing-trim` | 推荐 |
| 古籍影印 / 文言 | 居中式或全角式 | 配直排 |
## 二、加法模式 vs 减法模式
**这是认知误区的重灾区。**
### 加法模式(Additive,专业排版的方式)
- 标点本身 = **半宽**
- 加上一侧或两侧的**空隙**凑成全宽
- 调整对象 = 空隙(可拿掉、可缩半、可拉满)
- 采用方:InDesign、QuarkXPress、JIS、Adobe 全系
- 标点连用时:把相邻一侧的空隙拿掉
### 减法模式(Subtractive,大众默认认知)
- 标点本身 = **全宽**
- 通过"挤压"去掉部分宽度
- 调整对象 = 标点字面本身
- 采用方:方正自家排版软件、Word 中文版部分预设
- 问题:在加法模式的字体上做减法会算错
### 实操判断
**用 InDesign / Adobe 系统**:默认加法模式。选字体时优先选标点"偏靠式"的字库(思源、华文、蒙纳);规避方正大量正文字体(方正新书宋、方正悠黑、方正宋一)—— 它们把标点摆在字面正中("居中式"),与 Adobe 算法错位。
**用方正飞腾**:默认减法模式,方正字库内部自洽,不会出问题。
**Web / CSS**:现代 `text-spacing-trim: space-all` 是加法模式实现。
### 加法模式下标点的 3 类分组
| 类别 | 标点 | 空隙 |
|---|---|---|
| **第 1 类**:默认密排不加空 | 着重号、分隔号、连接号短横、日文 `?!` | 0 |
| **第 2 类**:一边加二分空(大陆 + 日文绝大多数) | 大陆问号 / 叹号 / 冒号 / 分号 / 逗号 / 顿号 / 句号;蝌蚪引号 ""'';圆括号 ();书名号《》 | 半宽 + 二分空 = 全宽 |
| **第 3 类**:两边各加四分空(港台多数 + 日文中点) | 港台问号 / 叹号 / 冒号;日文 `・` | 半宽 + 左 1/4 + 右 1/4 = 全宽 |
## 三、行末半角原则(GB/T 15834-2011 §5.1.10)
**强制规则**:标点排在一行末尾时,若为全宽字符**应占半角字符的宽度**。即"行末标点 → 半宽"。
- 这是中国大陆和多数中国出版社的硬性规范
- 视觉效果:行尾对齐(不会因末标点全宽撑出视觉外凸)
- 实现:InDesign "标点挤压" → 行尾减半(自动);CSS `hanging-punctuation: allow-end` 让标点悬挂到版心外
## 四、避头尾 4 级严格度(W3C CLReq §6.1.1)
**同一文档内必须统一一种严格度。**
### 0 级:none(不处理)
- 不做任何避头尾
- 见于港台部分报刊(标点居中无突兀)
- 大陆不推荐
### 1 级:basic(基本处理,最低标准)
- **不可在行首**:`。, 、 ; : ! ? … 》 」 』 ) 】`、所有"结束"括号和引号、连接号 `–`、间隔号 `·`、分隔号 `/`
- **不可在行尾**:`( 【 《 「 『 " '`、所有"开始"括号和引号
### 2 级:GB 法(大陆国标,推荐用于正式出版)
- basic 全部规则
- **加**:分隔号 `/` 也不可在行尾
- 这是中国大陆图书业的默认级别
### 3 级:strict(严格,推荐用于精装/正式出版)
- GB 法全部规则
- **加**:破折号 `——` 不可在行首
- **加**:省略号 `……` 不可在行首
- InDesign "简体中文避头尾" 默认即此级
### 完整字符表
#### 不可出现在行首
```
。,、;:?!…—··――
)】〗〕〉》」』〙〗⦆
’"
%‰‱℃℉°′″
/、‧/
```
#### 不可出现在行尾
```
(【〖〔〈《「『〘〖⦅
‘"
$¥€£¢₩₫
```
#### 不可分离(不可在中间断开)
```
—— 破折号(2 字宽视为一体)
…… 省略号(2 字宽视为一体)
123456 阿拉伯数字内部及小数点
50% 数字 + 百分号 / 千分号 / 度数
20℃ 数字 + 单位
±5 符号 + 数字
m² 被标记词 + 上下标
①② 注释记号 + 被注词
word 西文单词(按 hyphenation)
```
### 处理顺序:"先挤进后推出"
W3C 明文规则。
1. **第一步**:检查标点能否通过"宽度挤压"塞回前行末
- 行末全宽标点 → 半宽
- 连续标点 → 拿掉相邻一侧的空隙
- 中西间距 1/4 em → 1/8 em
2. **第二步**:仍塞不下,从前行末字推入下行
3. **第三步**:前行多出的空间按拉伸优先级处理
4. **第四步**:最后才平均加大字间距
**口诀**:**挤进只需腾半字宽,推出至少动一字宽;正文排版应尽量少调**。
### 推出后救济:均排(justify within)
行内调整无法整齐时,按拉伸优先级把空间分配出去。详见下一节。
## 五、行内挤压 / 拉伸优先级(W3C CLReq §6.2.2)
**这是排版引擎的内部算法表,知道了它你才知道为什么 InDesign 那样调字。**
### 挤压优先级(从高到低)
| 优先级 | 对象 | 挤压幅度 |
|---|---|---|
| a | **行末标点** | 固定半字宽(GB/T 15834-2011 §5.1.10) |
| b | 行内西文词距 | 最小 **1/4 em**,多处同等量 |
| c | 间隔号 `·` | 从两侧同等量挤,最小到 0(结果半字宽) |
| d | 夹注符号(括号)| 开始括号前侧、结束括号后侧,最小到半字宽 |
| e | 逗号 / 顿号 / 分号 | 后侧或两侧同等量挤,最小到半字宽 |
| f | 中西间距 | 最小 **1/8 em**(部分风格固定 1/4 em 不允许调) |
| g | 句号 / 问号 / 叹号 | 有空间则挤到半字宽(部分风格不允许调,因句末停顿大) |
### 拉伸优先级(从高到低)
| 优先级 | 对象 | 拉伸幅度 |
|---|---|---|
| a | 西文词距 | 最大 **1/2 em**,多处同等量 |
| b | 中西间距 | 从 1/4 em 默认值起,最大 **1/2 em**(实际多数风格只到 1/3 em)|
| c(最后选项) | 字间距 | 同等量拉,但**不可对禁则字间距拉伸**;连接号、分隔号及其前后字符避免拉伸 |
### 关键数值速查
| 间距 | 最小 | 默认 | 最大 |
|---|---|---|---|
| 西文词距 | 1/4 em | 1/3 em | 1/2 em |
| 中西间距 | 1/8 em | 1/4 em | 1/2 em |
| 间隔号两侧 | 0 | 1/4 em | 1/4 em |
| 行末标点 | 半字宽 | 半字宽 | 半字宽(不变) |
| 连续标点共 2 字 | 1 字 | 1.5 字 | 2 字 |
## 六、连续标点处理(W3C CLReq §6.3.2)
**最常见的灾难现场**:标点连用形成"白窟窿"。
未处理:
```
(明)钟惺、谭元春《唐诗归》钟评后二句"二
句儿童皆诵之,然其言自足不朽"。(清)弘历
↑↑↑
"。( 三个全角占 3 格
```
处理后:
```
(明)钟惺、谭元春《唐诗归》钟评后二句"二句儿童皆
诵之,然其言自足不朽"。(清)弘历《唐宋诗醇》评
↑↑
"。( 挤压到约 1.5 字宽
```
### 规则
- 任意两个相邻标点共 2 字宽时**应缩到 1.5 字宽**
- 可进一步缩到 1 字(但通常不缩到 1 字,避免读者错觉两符号是一个)
- 挤压方向让开始/结束括号紧靠被夹内容
### 实现
- InDesign:段落 → 中文排版设置 → "标点挤压" → 选"简体中文默认"或自定义
- CSS:`text-spacing-trim: space-all`(自动处理)
## 七、破折号专题
**最容易出错的单一符号。**
### 1. 码位优先级
1. **U+2E3A** TWO EM DASH `⸺` —— 正式码位,占 2 字一体,**首选**
2. **U+2014** EM DASH `—` × 2 —— 事实标准,思源字体通过 `ccmp` 替换为长横,**主用**
3. ❌ U+2015 HORIZONTAL BAR `―` —— 简中字库多数会断开
4. ❌ U+2500 BOX DRAWINGS LIGHT HORIZONTAL `─` —— 语义错误(制表符)
5. ❌ U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK `ー` —— 日文长音符
6. ❌ U+FF0D FULLWIDTH HYPHEN-MINUS `-` —— 半宽连接符
7. ❌ U+002D HYPHEN-MINUS `-` —— ASCII 连字符
### 2. 字体推荐(破折号正确实现)
**推荐**:
- 思源黑体 / 思源宋体(通过 OpenType `ccmp` 把连续两个 U+2014 替换为整段长横,再用 `locl` 在 CJK 语言下切换为字框居中字形)
- 苹方 PingFang
- HarmonyOS Sans / MiSans
**雷区**(破折号断开 / 顶格 / 下沉):
- 中易宋体、中易仿宋(破折号"无论如何接不上")
- 旧版微软雅黑(破折号下沉且双连超过两字宽)
- 华文黑体(破折号顶格不居中)
- 兰亭黑(破折号顶格且不居中)
### 3. 字体优先级陷阱(CSS)
❌ **错误**:
```css
font-family: "Helvetica", "PingFang SC"; /* 英文字体在前 */
```
连续两个 `—` 会优先取 Helvetica 字形,导致下沉、断开、双横之间留白。
✅ **正确(方案 A)**:删掉英文字体,用系统中文字体
```css
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
```
✅ **正确(方案 B)**:用 `unicode-range` 拆 `@font-face`
```css
@font-face {
font-family: "Helvetica Local";
src: local("Helvetica");
unicode-range: U+0000-007F; /* 只用于 ASCII */
}
body {
font-family: "Helvetica Local", "PingFang SC", sans-serif;
}
```
✅ **正确(方案 C)**:声明 `lang` 激活 `locl`
```html
<html lang="zh-CN">
```
### 4. 防破折号中间断开
**InDesign**:
1. 段落面板 → "禁止断字" 勾选(默认开)
2. 避头尾规则集 → "禁止分开的字符" → 加入 `U+2014`、`U+2015`、`U+2500`
3. 不要只勾"不换行"(那只是局部手动)
**Word**:
- 中文版"后置标点"里的 `―` 实际是 U+2015,不是 U+2014
- 要让 U+2014 也避头尾,须手动加进"自定义后置标点"
- 终极保险:选中单个 `—`,格式→字体→字符间距→缩放 200%,硬把单 em dash 变成两字宽(来自《排版与校对规范》)
**CSS**:
```html
<!-- 两个 em dash 之间禁止断行 -->
他说—&#8288;—我不去了。
```
### 5. 国标依据
- GB/T 15834-2011 §4.10 / §5.1.4:破折号占两个字位置、上下居中、**不能中间断开**
## 八、Unicode 码位速查(W3C CLReq 推荐)
| 符号 | Unicode | 推荐 | 不推荐替代 |
|---|---|---|---|
| 句号 | U+3002 。 | ✅ | U+FF0E . / U+002E . |
| 逗号 | U+FF0C , | ✅ | U+002C , |
| 顿号 | U+3001 、 | ✅ | — |
| 分号 | U+FF1B ; | ✅ | U+003B ; |
| 冒号 | U+FF1A : | ✅ | U+003A : |
| 问号 | U+FF1F ? | ✅ | U+003F ? |
| 叹号 | U+FF01 ! | ✅ | U+0021 ! |
| 弯双引号开 | U+201C " | ✅(横排)| — |
| 弯双引号闭 | U+201D " | ✅(横排)| — |
| 直角引号开 | U+300C 「 | ✅(直排)| — |
| 直角引号闭 | U+300D 」 | ✅(直排)| — |
| 双重直角引号开 | U+300E 『 | ✅(直排)| — |
| 双重直角引号闭 | U+300F 』 | ✅(直排)| — |
| 圆括号开 | U+FF08 ( | ✅ | U+0028 ( |
| 圆括号闭 | U+FF09 ) | ✅ | U+0029 ) |
| 书名号开 | U+300A 《 | ✅ | — |
| 书名号闭 | U+300B 》 | ✅ | — |
| 单书名号开 | U+3008 〈 | ✅ | — |
| 单书名号闭 | U+3009 〉 | ✅ | — |
| 破折号 | U+2E3A ⸺ / U+2014×2 —— | ✅ | U+2015 / U+2500 / U+30FC |
| 省略号 | U+2026×2 …… | ✅ | U+22EF(横直自动居中替代)|
| 连接号短横 | U+2013 – | ✅ | — |
| 连接号一字线 | U+2014 — | ✅ | — |
| 浪纹线 | U+FF5E ~ | ✅ | U+007E ~ |
| 间隔号 | U+00B7 · | ✅ | U+30FB / U+2027 / U+2022 |
| 分隔号 | U+002F / 或 U+FF0F / | ✅ | — |
| 着重号 | U+25CF ● 或 U+2022 • | ✅ | — |
## 九、CSS 完整实现(现代浏览器,2024+)
```css
.body-text {
/* 字间距:密排 */
letter-spacing: 0;
/* 标点空间挤压(加法模式实现) */
text-spacing-trim: space-all;
/* 标点悬挂到版心外(行尾标点视觉对齐) */
hanging-punctuation: allow-end;
/* 严格避头尾 */
line-break: strict;
/* 不在词中断 */
word-break: keep-all;
/* 超长 URL 允许换行 */
overflow-wrap: break-word;
/* 两端对齐 */
text-align: justify;
/* 中文字间分布 */
text-justify: inter-character;
/* 标点宽度优化(OpenType) */
font-feature-settings:
"halt" 1, /* 半宽间距 */
"palt" 1; /* 成比例排(标题用) */
}
/* 标题:不要 halt,标题密排 */
h1, h2, h3 {
font-feature-settings: "palt" 1; /* 仅成比例排 */
}
/* 网页 / H5 / 卡片正文:通常不做首行缩进 */
p {
text-indent: 0;
margin: 0 0 1em 0;
}
/* 书籍 / 公文 / 古典长文如需首行缩进,应由对应 template 明确指定 */
.book-copy p,
.official-doc p,
.classical-copy p {
text-indent: 2em;
margin: 0;
}
/* 引文段:不要斜体;缩进/边线/底色由版式决定 */
blockquote {
font-style: normal;
}
```
旧浏览器降级:用 `<wbr>` 手工断行;用脚本处理(如 `kerning.js`)。
## 十、检查清单(标点相关)
排印完成前必过:
- [ ] 标点风格(全角 / 半角 / 开明 / 居中)是否全文统一?
- [ ] 行末全宽标点是否变为半宽?
- [ ] 避头尾级别(basic / GB / strict)是否选定并启用?
- [ ] 连续标点是否被挤压到 1.5 字宽内?
- [ ] 破折号是否用了 U+2014×2(不是 4 个连字符)?
- [ ] 破折号字体是否选了思源 / 苹方而不是中易 / 旧版雅黑?
- [ ] 破折号是否被加入"禁止分开"集?
- [ ] 引号横排用弯""'',直排用直角「」『』?
- [ ] CSS `font-family` 是否把中文字体放在英文字体之前?
- [ ] HTML 是否声明了 `lang="zh-CN"` 或 `lang="zh-TW"`?
- [ ] 段落组织是否符合媒介:网页/卡片不机械首行缩进,书籍/公文/古典长文才按模板缩进?
- [ ] 中英混排是否有 1/4 字宽间距?