@topmindspace/tms-skills 0.1.19 → 0.2.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/CHANGELOG.md +21 -0
- package/README.en.md +5 -2
- package/README.md +4 -1
- package/package.json +5 -2
- package/topmind-cover/README.md +40 -0
- package/topmind-cover/SKILL.md +66 -0
- package/topmind-cover/package-lock.json +16 -0
- package/topmind-cover/package.json +16 -0
- package/topmind-cover/references/cover-styles.md +40 -0
- package/topmind-cover/scripts/audit_css.py +39 -0
- package/topmind-cover/scripts/audit_docs.py +58 -0
- package/topmind-cover/scripts/audit_skill.py +60 -0
- package/topmind-cover/scripts/audit_styles.py +54 -0
- package/topmind-cover/scripts/crop-cover.py +69 -0
- package/topmind-cover/scripts/negative_tests.py +71 -0
- package/topmind-cover/scripts/package_skill.py +188 -0
- package/topmind-wechat-post/README.md +49 -0
- package/topmind-wechat-post/SKILL.md +208 -0
- package/topmind-wechat-post/assets/themes/amber-review.json +35 -0
- package/topmind-wechat-post/assets/themes/graphite.json +35 -0
- package/topmind-wechat-post/assets/themes/minimal-ink.json +35 -0
- package/topmind-wechat-post/assets/themes/newsprint.json +35 -0
- package/topmind-wechat-post/assets/themes/tech-blue.json +35 -0
- package/topmind-wechat-post/package-lock.json +16 -0
- package/topmind-wechat-post/package.json +16 -0
- package/topmind-wechat-post/references/design.md +50 -0
- package/topmind-wechat-post/references/element-spec.md +162 -0
- package/topmind-wechat-post/references/known-pits.md +86 -0
- package/topmind-wechat-post/references/theme-map.md +139 -0
- package/topmind-wechat-post/references/typography-rules.md +62 -0
- package/topmind-wechat-post/references/wechat-constraints.md +106 -0
- package/topmind-wechat-post/references/workflow.md +102 -0
- package/topmind-wechat-post/references/writing-quality.md +129 -0
- package/topmind-wechat-post/scripts/audit_css.py +39 -0
- package/topmind-wechat-post/scripts/audit_docs.py +58 -0
- package/topmind-wechat-post/scripts/audit_skill.py +60 -0
- package/topmind-wechat-post/scripts/audit_styles.py +54 -0
- package/topmind-wechat-post/scripts/lint-wechat.py +446 -0
- package/topmind-wechat-post/scripts/md2wechat.py +1602 -0
- package/topmind-wechat-post/scripts/negative_tests.py +65 -0
- package/topmind-wechat-post/scripts/new-article.py +183 -0
- package/topmind-wechat-post/scripts/package_skill.py +188 -0
- package/topmind-wechat-post/scripts/push-to-topstream.py +226 -0
- package/topmind-wechat-post/scripts/scan_ai_flavor.py +464 -0
- package/topmind-wechat-post/scripts/sync-mapping.py +220 -0
- package/topmind-wechat-post/scripts/sync-status.py +187 -0
- package/topmind-x-article/README.md +40 -0
- package/topmind-x-article/SKILL.md +62 -0
- package/topmind-x-article/package-lock.json +16 -0
- package/topmind-x-article/package.json +16 -0
- package/topmind-x-article/references/publish-checklist.md +24 -0
- package/topmind-x-article/references/x-format.md +24 -0
- package/topmind-x-article/scripts/audit_css.py +39 -0
- package/topmind-x-article/scripts/audit_docs.py +58 -0
- package/topmind-x-article/scripts/audit_skill.py +60 -0
- package/topmind-x-article/scripts/audit_styles.py +54 -0
- package/topmind-x-article/scripts/md2x.py +121 -0
- package/topmind-x-article/scripts/negative_tests.py +74 -0
- package/topmind-x-article/scripts/package_skill.py +188 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# topmind-wechat-post · 技能侧设计摘要
|
|
2
|
+
|
|
3
|
+
> 技能边界以本文件、`SKILL.md` 和 `references/` 为准。不要另做一份用浏览器本地存储的公众号编辑器。
|
|
4
|
+
|
|
5
|
+
## 定位
|
|
6
|
+
|
|
7
|
+
- write 族**子技能**(`action_category: write` · `entrypoint: false` · pack `optional: true`)
|
|
8
|
+
- 触发意图:公众号 / 微信排版 / 定稿 / 发公众号
|
|
9
|
+
- 能力真源:`scripts/*.py`(stdlib)+ `references/*` + `assets/themes/*`(5 套,含 `amber-review`)
|
|
10
|
+
|
|
11
|
+
## 路径解析
|
|
12
|
+
|
|
13
|
+
`--base` → `TOPMIND_WECHAT_BASE` → `{TOPMIND_WORKSPACE}/40-创作|20-专题/{year}-公众号`;topstream 可选(`TOPSTREAM_ROOT`)。
|
|
14
|
+
**禁止**把个人绝对路径写进脚本默认值;兜底惯例路径必须经环境变量可覆盖。
|
|
15
|
+
|
|
16
|
+
## 三条路径
|
|
17
|
+
|
|
18
|
+
- **forward**:`notes/*.md` → 公众号稿(`source_file`)
|
|
19
|
+
- **reverse**:选题原创 → 公众号稿 → 可选回推(`target_file: pending`;回推**必须** `--assets`)
|
|
20
|
+
- **站外拉取**:在线精选站/转载整合 → 仍用 `reverse` + `pending`(站外源不进 notes)
|
|
21
|
+
|
|
22
|
+
## 质量三关 + 排版关
|
|
23
|
+
|
|
24
|
+
事实 / 逻辑 / 文字(scan_ai_flavor ≥85 + 报告腔四症状)→ lint 0 error → md2wechat `--embed-images`。
|
|
25
|
+
|
|
26
|
+
Desktop / 移动伴面只实现**约束子集**;完整语义以本目录 Python 为准。
|
|
27
|
+
|
|
28
|
+
## references 索引
|
|
29
|
+
|
|
30
|
+
| 文件 | 管什么 |
|
|
31
|
+
|------|--------|
|
|
32
|
+
| `workflow.md` | 流程/状态机/路径/站外拉取 |
|
|
33
|
+
| `known-pits.md` | 实操坑 |
|
|
34
|
+
| `element-spec.md` | 元素 → HTML 渲染规格 |
|
|
35
|
+
| `theme-map.md` | 主题键 ↔ 题材映射 |
|
|
36
|
+
| `wechat-constraints.md` | 平台硬约束(转换产物) |
|
|
37
|
+
| `typography-rules.md` | 阅读节奏/段长 |
|
|
38
|
+
| `writing-quality.md` | 质量三关 |
|
|
39
|
+
|
|
40
|
+
## 已知分叉与对拍要求
|
|
41
|
+
|
|
42
|
+
| 项 | 真源 | Desktop 子集 | 要求 |
|
|
43
|
+
|----|------|--------------|------|
|
|
44
|
+
| max-item | lint-wechat.py **70** | `WECHAT_MAX_ITEM` | 必须同值 |
|
|
45
|
+
| AI 结构扣分 | scan_ai_flavor.structural | `structuralDeduction()` | 同规则 |
|
|
46
|
+
| stat 管道行 | md2wechat 非 `\|` 丢弃 | wechat-format 同 | 同语义 |
|
|
47
|
+
| embed-images | `--embed-images` | `WechatService.exportViaScript` **优先**;否则 `embedLocalImagesWithChecklist` | 同效果 + 上传清单 |
|
|
48
|
+
| 导出真源 | `md2wechat.py` | 有 Python + 脚本时走 `wechat.exportViaScript` | 内置为回退 |
|
|
49
|
+
|
|
50
|
+
改动任一侧规则时,**同一次改动**更新另一侧并跑 `tests/plugin-wechat-ui.test.mjs` 对拍断言。
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# 元素渲染规范
|
|
2
|
+
|
|
3
|
+
`md2wechat.py` 把 Markdown 转成公众号内联样式 HTML 的**唯一依据**。
|
|
4
|
+
改渲染逻辑或新增语法时,先改本文件再改代码;`audit_inline()` 是本文件的自动校验版本。
|
|
5
|
+
|
|
6
|
+
合规分级(贯穿全篇):
|
|
7
|
+
|
|
8
|
+
| 级别 | 含义 | 处理原则 |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| **S** 安全 | 内联纯色/边框/字号,不会静默失效 | 可以放心依赖 |
|
|
11
|
+
| **D** 降级 | 可能被丢弃,但丢了不破坏结构与可读性 | 可用,但**不得作为唯一区分手段** |
|
|
12
|
+
| **X** 禁用 | 会静默失效或整段被吞 | 一律不用;`audit_inline` 判 ERROR |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 一、块级元素
|
|
17
|
+
|
|
18
|
+
| Markdown | 产物 | 级 | 说明 |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| `# 标题` | `<p style="20px/700/center">` | S | 不用 `<h1>`(微信按标题语义覆盖字号) |
|
|
21
|
+
| `## 标题` | `<h2 style="18px/700;color:text_strong">` + 自动编号 | S | 见下方「章节编号」 |
|
|
22
|
+
| `### 标题` | `<h3 style="16px/600">` | S | |
|
|
23
|
+
| `#### 标题` | `<h4 style="15px/600">` | S | |
|
|
24
|
+
| 段落 | `<p style="margin:0 0 {para_gap};line-height:{line_height};letter-spacing:0.5px;text-align:left;word-break:break-word">` | S | `text-align` 只允许 left/center/right |
|
|
25
|
+
| `---` | `<p style="center"><span style="display:inline-block;width:12%;height:2px;background:accent">` | D | 短横线依赖 `inline-block`;丢了会退化成一条不可见的行内元素 |
|
|
26
|
+
| `> 引用` | `<section>` + `background:surface` + `border-left:3px solid accent` | S | **不用 `<blockquote>`**:微信有原生引用样式会覆盖我们的配色 |
|
|
27
|
+
| `- 项` / `1. 项` | `<ul>`/`<ol>` + `<li>`,支持嵌套 | S | 圆点颜色取 accent |
|
|
28
|
+
| ```` ```lang ```` | `<section background:code_bg>` → 语言标签 `<section>` → 代码体 `<section style="white-space:pre-wrap;word-break:break-all">` | S | **不用 `<pre>`**;详见「代码块」 |
|
|
29
|
+
| 表格(≤3 列) | `<table style="width:100%">`,表头行是首个 `<tr>` | S | **不写 `table-layout:fixed`**,**不用 `thead/tbody/colgroup`** |
|
|
30
|
+
| 表格(≥4 列) | 自动转卡片:每行一张 `<section>`,首列作标题、其余「列名 + 值」成对 | S | 公众号列数 >4 必然横向溢出,卡片化是唯一稳的解法 |
|
|
31
|
+
| `` | `<section>` → `<p center>` → `<img style="max-width:100%;height:auto;display:block;margin:0 auto">` | S | **不用 `width:100%`**(小图被拉满变糊);**不用 `<figure>`** |
|
|
32
|
+
| `*图注*`(紧随图片) | `<p style="13px;color:text_light;center">` | S | 独立 `<p>`,不嵌在图片块里 |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 二、行内元素
|
|
37
|
+
|
|
38
|
+
| Markdown | 产物 | 级 | 视觉层级 |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `**文字**` | `<strong style="font-weight:600;color:text_strong">` | S | **锚点层**,全文 ≤5 处 |
|
|
41
|
+
| `*文字*` | `<em style="font-style:normal;color:text_muted">` | S | 弱化 |
|
|
42
|
+
| `` `代码` `` | `<code style="background:surface;color:accent;font-family:mono">` | S | |
|
|
43
|
+
| `==文字==` | `<strong>` + `background:accent_soft` | S | 容器层(高亮) |
|
|
44
|
+
| `++文字++` 或 `<u>文字</u>` | `<span style="border-bottom:2px solid accent_light;font-weight:600;color:text_strong">` | S | **标记层**,每段 1–3 个 |
|
|
45
|
+
| `~~文字~~` | `<span style="background:accent_soft;font-weight:600">` | S | 半高亮 |
|
|
46
|
+
| `[!文字]` | `<span style="11px;color:accent;background:accent_soft;padding:1px 6px">` | S | 徽章;不用 `inline-block` |
|
|
47
|
+
| `[文字](url)` | 正文 `文字` + 上标 `[n]`,文末「参考链接」块 | S | 公众号正文不支持可点外链 |
|
|
48
|
+
|
|
49
|
+
### 视觉层级(三层,写稿时的标记纪律)
|
|
50
|
+
|
|
51
|
+
| 层 | 手段 | 频率 | 用错会怎样 |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| **锚点层** | `**加粗**` | 全文 **≤5 处** | 到处加粗 = 没有重点 |
|
|
54
|
+
| **标记层** | `++下划线++` | **覆盖 ≥60% 的正文段落**,每段 1–3 个 4–15 字短语 | 缺失 = 正文变成一堵灰墙,读者无处落脚 |
|
|
55
|
+
| **容器层** | `==高亮==`、`::: 容器`、引用块 | 按需 | 堆太多会显得花 |
|
|
56
|
+
|
|
57
|
+
标记层是**出现频率最高**的一层,也是最容易被漏掉的一层。
|
|
58
|
+
|
|
59
|
+
`lint-wechat.py` 分两层判:**标记覆盖率 ≥60%**(带标记的正文段落数 ÷ 正文段落数,低于就报「跳读时没有落点」)+ **锚点加粗 ≤5 处**(超出就报「把标记当锚点用」)。
|
|
60
|
+
|
|
61
|
+
**不用「强调占比」这个口径**——它把两层合成一个数,会同时掩盖两种病:锚点爆表(加粗 123 处)和标记归零(下划线 0 处)能算出相近的占比,但修法完全不同。占比还容易凑:35 段里只标 5 段、每段标 20 字也能到 10%,而整段划线等于没标。覆盖率对应的是「还有几段没标」这个可执行动作。
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 三、容器
|
|
66
|
+
|
|
67
|
+
`:::` 是自研中间标记(公众号不认 Markdown,由 `md2wechat.py` 转成内联样式 HTML)。
|
|
68
|
+
|
|
69
|
+
| 写法 | 产物 | 用在哪 |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `::: note` | 灰边说明块 | 补充说明 |
|
|
72
|
+
| `::: tip` | 绿边提示块 | 实操建议 |
|
|
73
|
+
| `::: warn` | 琥珀边注意块 | 风险提醒 |
|
|
74
|
+
| `::: danger` | 红边警告块 | 严重风险 |
|
|
75
|
+
| `::: pull` | 上下框线 + 居中金句 | 全文点睛,1–2 处 |
|
|
76
|
+
| `::: stat` | 浅底卡片 + 大号 accent 数字 | 关键数据(`数值 \| 说明` 每行一条) |
|
|
77
|
+
| `::: dialogue` | 说话人 + 气泡 | 访谈、问答 |
|
|
78
|
+
| `::: toc` | 前言导读卡 | 一般不用手写,见「自动导读」 |
|
|
79
|
+
| `::: sign` | 尾部签名区 | 一般不用手写,见「自动签名」 |
|
|
80
|
+
|
|
81
|
+
容器名拼错会**静默降级成 note**——`lint-wechat.py` 会报未知容器。
|
|
82
|
+
别名(`info`/`memo`→note,`success`/`ok`→tip,`quote`/`golden`→pull,`data`/`metric`→stat,
|
|
83
|
+
`chat`/`talk`→dialogue)等价。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 四、三段自动行为
|
|
88
|
+
|
|
89
|
+
### 章节编号
|
|
90
|
+
|
|
91
|
+
- 标题里**手写的序号会被剥离**:`## 一、官方总表` → `01 官方总表`
|
|
92
|
+
- 剥离规则:中文序号(`一、`/`第一、`)、阿拉伯序号(`1.`/`01 `)
|
|
93
|
+
- 带负向断言保护:`## 3.4× 成本` **不会**被误剥成 `4× 成本`
|
|
94
|
+
- 编号由 `h2_style` 决定:`number`(01 + 左竖条,默认)/ `bar`(仅左竖条)/
|
|
95
|
+
`underline`(下划线)/ `center`(上下框线)/ `plain`(无装饰)
|
|
96
|
+
- **末章若为收束类用 `∞` 而不是顺延数字**:标题匹配
|
|
97
|
+
总结/结语/小结/尾声/后记/写在最后/写在后面/收尾/结尾/余论 时,编号取 `∞`
|
|
98
|
+
(`number` 样式下生效)。理由:数字编号暗示"还有下一节",与收束章的定位打架。
|
|
99
|
+
实测 `## 六、总结` → `∞ 总结`,其余仍为 `01`…`05`。
|
|
100
|
+
- **写稿时不要手写序号**:手写后序号变成不可编程的字符串,
|
|
101
|
+
换编号样式、加引用、做导航都得手改一遍
|
|
102
|
+
|
|
103
|
+
### 前言导读
|
|
104
|
+
|
|
105
|
+
- 触发条件(满足任一,且 `toc` 未被 `--no-toc` 关闭):
|
|
106
|
+
- 章节数 ≥ `toc_min_h2`(默认 4)
|
|
107
|
+
- 章节数 ≥ 3 且正文 ≥ `toc_min_chars`(默认 2000 中文字)
|
|
108
|
+
- 位置:**首个正文段落之后**(不是标题与封面图之间)
|
|
109
|
+
- 内容:最多 `toc_max`(默认 5)条,超出时附注「……共 N 节」
|
|
110
|
+
——**不假装全文只有这几节**
|
|
111
|
+
- **导读的标记必须与正文标题一致**:
|
|
112
|
+
- 标题带编号(`number`)→ 导读也编号,末章收束类同为 `∞`
|
|
113
|
+
- 标题不带编号(`center`/`underline`/`plain`)→ 导读用中性圆点 `·`,
|
|
114
|
+
**不能凭空造出 01/02**(否则读者在正文里找不到对应的编号)
|
|
115
|
+
- 显式 `::: toc` 优先于自动插入
|
|
116
|
+
|
|
117
|
+
### 尾部签名
|
|
118
|
+
|
|
119
|
+
`--signature` 三态:
|
|
120
|
+
|
|
121
|
+
| 值 | 行为 |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `auto`(默认) | 稿件末尾**已自带**签名/CTA 则不再追加,避免出现两处签名区 |
|
|
124
|
+
| `on` | 无条件追加 |
|
|
125
|
+
| `off` | 只在显式写了 `::: sign` 时渲染 |
|
|
126
|
+
|
|
127
|
+
- 署名用占位 `{{作者名}}`,**不替用户编造人名**;`--author` / `--author-bio` 可填
|
|
128
|
+
- 判定「已自带」的口径:正文末尾 8 个非空段落内出现
|
|
129
|
+
`点赞 / 在看 / 三连 / 点个关注 / 欢迎关注 / 关注「 / 扫码 / 分享给 / 我是…,`
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 五、代码块
|
|
134
|
+
|
|
135
|
+
- **不用 `<pre>`**:公众号端不自动换行,窄屏横向溢出,且格式检测会标风险项
|
|
136
|
+
- 用 `<section>` + `white-space:pre-wrap` + `word-break:break-all`
|
|
137
|
+
- 缩进与换行由代码自身提供:**HTML 源码里不在 pre-wrap 容器内插入任何格式化换行**
|
|
138
|
+
(插了就会渲染出伪空行和大左缩进)
|
|
139
|
+
- **色板跟随主题**(`code_scheme`):
|
|
140
|
+
- `mono`(默认):只用「主色 + 明暗层级」。注释最暗、字符串次之、
|
|
141
|
+
关键字取主色的提亮版、其余用 `code_text`
|
|
142
|
+
- `palenight`:Material Palenight 的 16 色,**已不推荐**——
|
|
143
|
+
天蓝/翠绿/橙红与砖红、琥珀等主色毫无关系,一篇文章里会出现两套色彩语言
|
|
144
|
+
- 语言标签显示在代码体上方,字号 11px,颜色取 accent
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 六、`audit_inline()` 检查清单
|
|
149
|
+
|
|
150
|
+
每次生成 HTML 后自动跑,`ERROR` 必须清零。检查项已按本文件分级:
|
|
151
|
+
|
|
152
|
+
**ERROR**:`<div>` `<figure>` `<figcaption>` `<pre>` `<thead>` `<tbody>` `<colgroup>`
|
|
153
|
+
`<h1>` `<iframe>` `<video>` `<script>` `<style>`;`text-align` 非标准值;
|
|
154
|
+
px 固定宽度;`white-space:pre/nowrap`;`position/float/transform/opacity`;
|
|
155
|
+
`display:flex/grid`;`-webkit-*`;`linear-gradient`;`box-shadow`;`rgba()/hsla()`;
|
|
156
|
+
`var(--)`;`@media/@keyframes`;`class` 属性;Markdown 标记残留(`==`、`**`)
|
|
157
|
+
|
|
158
|
+
**WARN**:`table-layout:fixed`(列宽均分)、`display:inline-block`(非常规 display 值)、
|
|
159
|
+
`border-radius`(可能被丢,属优雅降级)、图片 `width:100%`、`id` 属性、
|
|
160
|
+
`<img width="...">` 属性
|
|
161
|
+
|
|
162
|
+
WARN 不是「可以忽略」,而是「已知风险,需确认是否可接受」。
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 已知坑(实测踩过,写入质检与操作纪律)
|
|
2
|
+
|
|
3
|
+
## 1. `--embed-images` 不加 = 粘贴丢图
|
|
4
|
+
|
|
5
|
+
链路:HTML `src="images/xx.png"` → 浏览器复制序列化成 `file://` → 公众号后台取不到 → **整张 `<img>` 消失**(不是裂图)。
|
|
6
|
+
|
|
7
|
+
**修法**:`md2wechat.py --embed-images`(base64 内嵌)。`images/` 仍导出作占位符兜底。
|
|
8
|
+
|
|
9
|
+
自检:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
grep -c 'src="images/' <包>/*-公众号版.html # 期望 0
|
|
13
|
+
grep -c 'src="data:image/' <包>/*-公众号版.html # 期望 = 正文图数
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 2. 图片 basename 撞名 → 链式全挂
|
|
17
|
+
|
|
18
|
+
`resolve_image()` 按 **basename** 复制到 `images/`。`images/bare/01.png` 与 `images/01.png` 同名 → 产出 `01-1.png` → 删副本 = HTML 图全挂。
|
|
19
|
+
|
|
20
|
+
**铁律**:
|
|
21
|
+
|
|
22
|
+
- 正文只引用 `images/XX.png`,包内只放正文那一套
|
|
23
|
+
- 多套用不同前缀(`full-` / `bare-`),不要靠子目录区分
|
|
24
|
+
- `-1` 副本不是垃圾,是 HTML 正在引用的文件
|
|
25
|
+
|
|
26
|
+
自检:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
find <包> -name "*-1.*" # 不应有任何结果
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 3. 同一文件并行 Edit 只落盘一部分
|
|
33
|
+
|
|
34
|
+
同一条消息多个 Edit:工具可能都回 Successfully,**只有部分落盘**。
|
|
35
|
+
|
|
36
|
+
**纪律**:改完必须 `grep` 关键词复核;多处改动合成一个脚本一次写完,或串行分轮。
|
|
37
|
+
|
|
38
|
+
## 4. `::: stat` 非管道行被静默丢弃
|
|
39
|
+
|
|
40
|
+
容器内每行必须 `数值 | 说明`。不带 `|` 的行整块消失且无报错。生成 HTML 后抽查容器内容。
|
|
41
|
+
|
|
42
|
+
## 5. 表格单元格 `|` 要转义
|
|
43
|
+
|
|
44
|
+
生成 markdown 表时 `.replace(/\|/g, '\\|')`。JS 模板字符串里写 `\\\\|` 才得到 `\\|`。
|
|
45
|
+
|
|
46
|
+
## 6. 代码块长行被 `break-all` 词中切断
|
|
47
|
+
|
|
48
|
+
JSON 示例行宽压到 ~55 字符;真实节选注明「节选」,字段值不得改写。
|
|
49
|
+
|
|
50
|
+
## 7. 图文两套同名 + 清理 `bare/`
|
|
51
|
+
|
|
52
|
+
完整版与纯图形版共处包内必撞名。完整版放研究层;交付包只留正文用的一套。
|
|
53
|
+
|
|
54
|
+
## 8. 外部工具改稿的数字漂移
|
|
55
|
+
|
|
56
|
+
「比值对但绝对值错」= 从别的口径倒推。先脚本回溯 `results/*.json`,再改文字。
|
|
57
|
+
|
|
58
|
+
## 9. 表格手抄必漂移
|
|
59
|
+
|
|
60
|
+
从数据源生成(脚本直出)。同一文档两份拷贝时 `md5` 比对;派生汇总字段也是数据,要回填。
|
|
61
|
+
|
|
62
|
+
## 10. qu-aiwei 误报别改坏
|
|
63
|
+
|
|
64
|
+
- 「排比三段式」可能误报数据变化(从 A 到 B)→ **保留**
|
|
65
|
+
- 专有名词「复盘」→ 不改;动词套话 → 改
|
|
66
|
+
|
|
67
|
+
## 11. 满分仍「太 AI」
|
|
68
|
+
|
|
69
|
+
词面 100 分只证明无套话。再查四症状:段末金句癖 / 节奏过分整齐 / 没有「我」与场景 / 报告体标注。
|
|
70
|
+
|
|
71
|
+
## 12. 加「人味」用力过猛
|
|
72
|
+
|
|
73
|
+
社交垫词(「先说个好消息」「说白了」)不是人味。判据:删掉后读者少知道了什么?
|
|
74
|
+
|
|
75
|
+
## 13. 长文零容器 = 视觉窒息
|
|
76
|
+
|
|
77
|
+
每 1500–2500 字至少一个 `::: stat` 或 `::: pull`。8000 字纯段落反面教材。
|
|
78
|
+
|
|
79
|
+
## 14. 复制依赖 `execCommand`
|
|
80
|
+
|
|
81
|
+
Safari 可能失败 → 手动全选复制。Desktop/移动端提供按钮 + 失败提示。
|
|
82
|
+
|
|
83
|
+
## 15. 合规自检误报
|
|
84
|
+
|
|
85
|
+
- 正文 `<h2>` 是有意设计(不用 h1)
|
|
86
|
+
- `pre` 会命中英文单词;只在 `<article>` 内按标签形式匹配
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# 题材 → 主题映射
|
|
2
|
+
|
|
3
|
+
「按题材分主题」的规约。主题文件在 `assets/themes/*.json`,
|
|
4
|
+
命令行 `--theme` 选主题,`--list-themes` 看全部,`genre:题材` 按题材自动选。
|
|
5
|
+
|
|
6
|
+
## 已注册主题
|
|
7
|
+
|
|
8
|
+
| 主题 | 标识 | 主色 | 标题样式 | 圆角 | 适用题材 |
|
|
9
|
+
|---|---|---|---|---|---|
|
|
10
|
+
| 极简黑白灰 | `minimal-ink` | `#A6524A` 砖红 | number | 4px | **默认**、观点、深度分析、随笔 |
|
|
11
|
+
| 科技蓝 | `tech-blue` | `#185FA5` 蓝 | number | 6px | 教程、实操、工具测评、建站 |
|
|
12
|
+
| 石墨灰阶 | `graphite` | `#52525B` 石墨 | underline | 0px | 技术说明、专业评论、方法、原理 |
|
|
13
|
+
| 报纸纸感 | `newsprint` | `#8C5A3C` 棕(衬线) | center | 0px | 复盘、特稿、行业观察、长文 |
|
|
14
|
+
| 琥珀评测 | `amber-review` | `#B45309` 琥珀 | number | 6px | 评测、模型评测、数据对比、榜单、速览 |
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# 看清单
|
|
18
|
+
python3 scripts/md2wechat.py --list-themes
|
|
19
|
+
|
|
20
|
+
# 指定主题(三种写法都可以)
|
|
21
|
+
--theme amber-review # 标识
|
|
22
|
+
--theme 琥珀评测 # 中文名
|
|
23
|
+
--theme genre:评测 # 按题材自动选
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 选题材的原则
|
|
27
|
+
|
|
28
|
+
**一句话**:主题跟着**题材**走,不跟着心情走。同一个题材永远用同一套主题,
|
|
29
|
+
读者才能形成视觉记忆。换题材时才换主题。
|
|
30
|
+
|
|
31
|
+
| 判断依据 | 走哪个主题 |
|
|
32
|
+
|---|---|
|
|
33
|
+
| 有大量数据对比、榜单、多维评分 | 琥珀评测 |
|
|
34
|
+
| 有步骤、命令、可复现的操作过程 | 科技蓝 |
|
|
35
|
+
| 讲原理、讲机制、专业观点输出,需要克制 | 石墨灰阶 |
|
|
36
|
+
| 讲一个完整案例的来龙去脉、时间跨度长 | 报纸纸感 |
|
|
37
|
+
| 观点表达、行业观察、随笔,没有明显题材特征 | 极简黑白灰(默认) |
|
|
38
|
+
|
|
39
|
+
**题材交叉时**(如"带步骤的模型评测"):看**读者来干什么**。
|
|
40
|
+
来抄操作步骤的 → 科技蓝;来看结论和数据的 → 琥珀评测。
|
|
41
|
+
|
|
42
|
+
## 主题之间必须一致的东西
|
|
43
|
+
|
|
44
|
+
换主题**只换色彩与标题形态**,以下参数在所有主题间保持一致,不要随手改:
|
|
45
|
+
|
|
46
|
+
| 参数 | 统一值 | 理由 |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| 正文字号 | 16px | 公众号长文阅读舒适区 |
|
|
49
|
+
| 行高 | 1.75(报纸纸感 1.8) | 低于 1.7 会挤 |
|
|
50
|
+
| 段间距 | 22px(报纸纸感 24px) | 与行高成比例 |
|
|
51
|
+
| 对齐 | `left` | 中文 `justify` 会产生「河流」并触发格式告警 |
|
|
52
|
+
| 章节编号 | 全部由排版层生成 | 见 `element-spec.md`「章节编号」;末章收束类用 `∞` |
|
|
53
|
+
| 视觉层级规则 | 锚点层 ≤5 / 标记层每段 1–3 | 与主题无关,是阅读规律 |
|
|
54
|
+
|
|
55
|
+
**这些是阅读规律,不是审美偏好**,任何主题都不该改。
|
|
56
|
+
|
|
57
|
+
## 每套主题必须提供的字段
|
|
58
|
+
|
|
59
|
+
新增主题时字段缺一个,就会继承默认主题的值——**这正是历史 bug 的成因**:
|
|
60
|
+
`tech-blue` 当年只写了 14 个字段,`mark_bg` 落到默认主题的砖红浅底 `#FAF0EE`,
|
|
61
|
+
一套蓝色主题里冒出砖红高亮,于是从来没人敢用它。现在 `load_theme()` 会按各自主色
|
|
62
|
+
自动派生 `accent_light` / `accent_soft`,但**其余字段仍需显式写全**。
|
|
63
|
+
|
|
64
|
+
```jsonc
|
|
65
|
+
{
|
|
66
|
+
"id": "标识(英文,命令行用)",
|
|
67
|
+
"name": "中文名",
|
|
68
|
+
"genre": ["题材1", "题材2"], // `--theme genre:题材` 按此匹配,也用于 --list-themes 展示
|
|
69
|
+
|
|
70
|
+
// 主色三件套:派生色可不写(自动按 accent 算),写了则以文件为准
|
|
71
|
+
"accent": "#______", // 唯一强调色
|
|
72
|
+
"accent_light": "#______", // 关键词下划线(标记层)
|
|
73
|
+
"accent_soft": "#______", // 高亮底 / 徽章底
|
|
74
|
+
|
|
75
|
+
// 文字四级
|
|
76
|
+
"text": "#______", // 正文
|
|
77
|
+
"text_strong": "#______", // 加粗、标题
|
|
78
|
+
"text_muted": "#______", // 斜体、脚注
|
|
79
|
+
"text_light": "#______", // 图注、数值说明、导读截断提示
|
|
80
|
+
|
|
81
|
+
// 面与线
|
|
82
|
+
"surface": "#______", // 卡片底(stat/引用/签名/导读共用)
|
|
83
|
+
"border": "#______", // 表格线、金句上下框线
|
|
84
|
+
"img_border": "#______", // 图片描边
|
|
85
|
+
|
|
86
|
+
// 代码块:色板按 accent 自动生成,配色方案二选一
|
|
87
|
+
"code_bg": "#______",
|
|
88
|
+
"code_text": "#______",
|
|
89
|
+
"code_scheme": "mono", // mono(推荐,只用主色+明暗)| palenight(不推荐)
|
|
90
|
+
|
|
91
|
+
// 四种语义色(容器左边框)
|
|
92
|
+
"c_note": "#______", "c_tip": "#______",
|
|
93
|
+
"c_warn": "#______", "c_danger": "#______",
|
|
94
|
+
|
|
95
|
+
// 形态
|
|
96
|
+
"radius": "0px | 4px | 6px", // 全主题统一圆角;直角最保守
|
|
97
|
+
"h2_style": "number | bar | underline | center | plain",
|
|
98
|
+
"line_height": "1.75",
|
|
99
|
+
"para_gap": "22px",
|
|
100
|
+
"align": "left",
|
|
101
|
+
"font_size": "16px",
|
|
102
|
+
|
|
103
|
+
// 结构组件
|
|
104
|
+
"toc": true, "toc_max": 5, "toc_min_h2": 4, "toc_min_chars": 2000,
|
|
105
|
+
"table_max_cols": 3, // 超过就转卡片化
|
|
106
|
+
|
|
107
|
+
"font_stack": "...", "mono_stack": "..."
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 加一套新主题的步骤
|
|
112
|
+
|
|
113
|
+
1. 在 `assets/themes/` 写 `{id}.json`,字段按上表写全
|
|
114
|
+
2. 跑 `python3 scripts/md2wechat.py --list-themes` 确认能被列出
|
|
115
|
+
3. 用一篇真实稿跑一遍,确认 `合规自检` 为 0 ERROR:
|
|
116
|
+
`python3 scripts/md2wechat.py --input 稿.md --out-dir /tmp/t --slug t --theme {id}`
|
|
117
|
+
4. 在本文件的主题表里登记一行
|
|
118
|
+
5. 目视核对:**下划线色、高亮底、代码块关键字色是否都跟本主题主色同源**
|
|
119
|
+
(不同源 = 又出现了色彩外溢)
|
|
120
|
+
|
|
121
|
+
## 主题与视觉层级的配合
|
|
122
|
+
|
|
123
|
+
三层标记手段在所有主题下的表现:
|
|
124
|
+
|
|
125
|
+
| 层 | 手段 | 主题相关性 |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| 锚点层 | 主色加粗 / 深色底白字引用 | 用 `text_strong`,**不用 accent**——浅色主题下 accent 加粗不够重 |
|
|
128
|
+
| 标记层 | 下划线 `accent_light` | 浅色主题用浅色调(砖红→`#E3BAB3`);深色主题用主色本身(石墨→`#52525B`) |
|
|
129
|
+
| 容器层 | 底色 `surface` + 左边框 `accent` | 全主题统一结构,只换色 |
|
|
130
|
+
|
|
131
|
+
石墨灰阶的下划线特意用主色本身而不是浅色调:灰色主题里浅灰下划线几乎看不见,
|
|
132
|
+
起不到标记作用。**下划线色的选择标准是「能不能看见」,不是「够不够淡」。**
|
|
133
|
+
|
|
134
|
+
### `h2_style` 会连带影响导读
|
|
135
|
+
|
|
136
|
+
导读(前言看点)的标记跟随 `h2_style`:带编号的主题(`minimal-ink`/`tech-blue`/`amber-review`)
|
|
137
|
+
导读也编号,末章收束类同为 `∞`;不带编号的主题(`graphite` 下划线 / `newsprint` 上下框线)
|
|
138
|
+
导读只能用中性圆点。**换主题时导读会自动跟着变,不用手改**——但如果发现"导读有 01、正文没编号",
|
|
139
|
+
那是渲染器 bug,不是主题配置问题。
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 公众号改稿规则(Stage 1 执行标准)
|
|
2
|
+
|
|
3
|
+
从技术博客 Markdown 到公众号稿,改的是**阅读节奏**,不是技术事实。事实、数据、链接一律不动。
|
|
4
|
+
|
|
5
|
+
## 必须做
|
|
6
|
+
|
|
7
|
+
1. **开头 150 字内给钩子**:结论、反差或悬念,不要背景铺垫。原文首段若是长背景,压缩或后移。
|
|
8
|
+
2. **段落切分**:单段 ≤ 110 字(约 4 行手机屏)。长段按语义断点拆开,不要机械等分。
|
|
9
|
+
3. **小标题序号化**:二级标题统一「一、二、三」或「01 / 02」,读者能感知进度。
|
|
10
|
+
4. **列表项 ≤ 70 字**:超长列表项改成「加粗小标题 + 短说明」的段落组。
|
|
11
|
+
5. **重点加粗**:只加粗结论句和关键数据,全篇加粗密度控制在每 20 字不超过 1 处。
|
|
12
|
+
6. **长句拆短**:单句 > 45 字且有逗号堆叠时,拆成两句。
|
|
13
|
+
7. **图注统一**:`*▲ 图 N:说明*`,图注要说出「看什么」,不要只重复图片名。
|
|
14
|
+
8. **外链处理**:保留可点性无意义,改为「来源:XXX(URL)」的灰色小字或直接写机构名。
|
|
15
|
+
9. **结尾三段式**:一句总结结论 → 一句抛出问题/邀请讨论 → 引导关注语。
|
|
16
|
+
|
|
17
|
+
## 不要做
|
|
18
|
+
|
|
19
|
+
- 不改技术事实、不改数据、不改评测结论
|
|
20
|
+
- 不删代码块(公众号读者需要可复制的配置/命令)
|
|
21
|
+
- 不把「我」改成「笔者」「作者」等腔调词,第一人称是这类文章的信任来源
|
|
22
|
+
- 不加「随着...的发展」「在当今时代」这类 AI 腔 / 八股开场
|
|
23
|
+
- 不加 emoji 堆砌的小标题
|
|
24
|
+
- 不为了凑字数注水,公众号长文 3000-6000 字是合理区间
|
|
25
|
+
- 中英文/数字之间忘了空格没关系(lint --fix 会补),但**别手动在代码和链接里加**
|
|
26
|
+
|
|
27
|
+
## 容器语法使用时机(v2)
|
|
28
|
+
|
|
29
|
+
| 时机 | 用法 |
|
|
30
|
+
|---|---|
|
|
31
|
+
| 一句话核心观点、想让它从版面上跳出来 | `::: pull` 金句容器(大字居中,前后留白) |
|
|
32
|
+
| 关键数据对比(如「62.7% vs 99.9%」) | `::: stat` 数据卡(大数字 + 注释) |
|
|
33
|
+
| 补充但不打断主线的信息 | `::: note` 灰色提示框 |
|
|
34
|
+
| 操作建议、经验窍门 | `::: tip` 绿色提示框 |
|
|
35
|
+
| 容易踩的坑、官方风险提示 | `::: warn` 橙色 / `::: danger` 红色 |
|
|
36
|
+
| 观点交锋、问答式段落(A: B:) | `::: dialogue` 对话容器 |
|
|
37
|
+
| 版本号、状态标签、关键词打标 | `[!新特性]` 行内徽章 |
|
|
38
|
+
| 全文最重要的 1-3 句 | `==高亮==`(节制使用) |
|
|
39
|
+
|
|
40
|
+
原则:**每 800 字最多 1 个容器**,容器是调味料不是主菜;连续两种容器相邻会显得杂乱。
|
|
41
|
+
|
|
42
|
+
## 去 AI 腔检查点
|
|
43
|
+
|
|
44
|
+
- 排比三连句("不是 A,不是 B,而是 C")出现超过 2 次 → 改写
|
|
45
|
+
- 「值得注意的是」「综上所述」「不难看出」→ 删
|
|
46
|
+
- 每段都以「首先/其次/最后」开头 → 打散
|
|
47
|
+
- 形容词堆叠("极其轻巧稳定的架构")→ 留一个
|
|
48
|
+
|
|
49
|
+
## 排版参数基线(调研印证的通用规范)
|
|
50
|
+
|
|
51
|
+
- 正文 16px、行距 1.75、字间距 0、左对齐(不用 justify,会被格式检测判为非标准值)
|
|
52
|
+
- 段间距 22px 代替首行缩进(手机端惯例)
|
|
53
|
+
- 正文色 #333(纯黑 #000 在白底上过刺眼),辅助文字 #888
|
|
54
|
+
- 代码块深底浅字(浅灰底代码块在部分安卓机型上对比度不足)
|
|
55
|
+
|
|
56
|
+
## 交付前自检
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python3 scripts/lint-wechat.py --input 公众号稿.md --fix
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
错误项(长段 > 200 字 / 图片缺失/过大)必须清零;警告项逐条判断是否接受。
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# 微信公众号编辑器硬约束
|
|
2
|
+
|
|
3
|
+
所有排版决策的依据。违反任一条,粘贴后的效果就会与预览不一致。
|
|
4
|
+
|
|
5
|
+
> **先厘清一个常见误解**:`::: stat`、`::: pull`、`==高亮==`、`[!徽章]` 这些**不是公众号语法**。
|
|
6
|
+
> 公众号后台是富文本编辑器,**根本不认 Markdown**。它们是我们自研的「中间标记」,
|
|
7
|
+
> 由 `md2wechat.py` 转成内联样式 HTML 后才粘进后台。所以判断「公众号支不支持」,
|
|
8
|
+
> 看的是**转换产物**(`section/p/span/div` + 内联样式),而不是 `:::` 本身。
|
|
9
|
+
> 本文件约束的就是「转换产物」必须遵守的规则。
|
|
10
|
+
|
|
11
|
+
## 1. 只保留内联样式
|
|
12
|
+
|
|
13
|
+
- 剥离 `<style>` 标签、`<link>`、`class` 属性、`id` 属性
|
|
14
|
+
- 剥离 `<script>`,所有交互失效
|
|
15
|
+
- **不用 `<div>`**:新版编辑器底层是 ProseMirror,白名单里没有 div。
|
|
16
|
+
div 包裹的块会连同它的背景、内边距、圆角**被整段吞掉**,只剩文字,
|
|
17
|
+
表面看就是「整篇没 CSS」。这是「粘贴后样式全丢」的头号元凶,比渐变被吃更隐蔽。
|
|
18
|
+
**一律用 `<section>`**(标签级红线清单见 `element-spec.md`)。
|
|
19
|
+
- **结论**:HTML 里每一个样式都必须写成 `style="..."`,不许出现 class 依赖
|
|
20
|
+
|
|
21
|
+
## 2. 外链
|
|
22
|
+
|
|
23
|
+
- 正文 `<a href>` 指向非白名单域名时,链接不可点(未认证订阅号尤其如此)
|
|
24
|
+
- 「阅读原文」是唯一官方外链入口
|
|
25
|
+
- **结论**:外链降级为「灰色小字 URL 文本」,读者手动复制;重要链接放「阅读原文」
|
|
26
|
+
|
|
27
|
+
## 3. 图片
|
|
28
|
+
|
|
29
|
+
- 本地相对路径 / `file://` 一律失效
|
|
30
|
+
- 远程图片在粘贴进入编辑器时,微信**多数情况下会自动抓取**转存素材库,但不保证(防盗链、content-type 不对、超时都会失败)
|
|
31
|
+
- **宽度用 `max-width:100%;height:auto`,绝不用 `width:100%`**:
|
|
32
|
+
正文容器约 677px,`width:100%` 会把 400px 的小截图强行拉满变糊,竖图更糟。
|
|
33
|
+
`max-width` 让大图缩到容器宽、小图保持原尺寸并居中。
|
|
34
|
+
- `WebP` 在正文图里不被支持(需转 PNG/GIF);`SVG` 完全不支持(需光栅化)
|
|
35
|
+
- **结论**:默认走「导出图片包 + 手动上传」;用 CDN 外链时必须提供上传清单兜底
|
|
36
|
+
|
|
37
|
+
## 4. 代码与特殊语法
|
|
38
|
+
|
|
39
|
+
- 无代码块语法,**不要用 `<pre>`**:pre 不自动换行,窄屏横向溢出,且会被格式检测标为风险项
|
|
40
|
+
- 用 `<section style="white-space:pre-wrap;word-break:break-all;">` + 等宽字体 + 深色底模拟
|
|
41
|
+
- 不支持 mermaid、LaTeX、SVG 内联(部分 SVG 会被剥离)
|
|
42
|
+
- `<iframe>`、`<video>` 会被剥离,视频只能用公众号自带的腾讯视频/视频号组件
|
|
43
|
+
- **结论**:mermaid / 公式必须预渲染成 PNG 再插图
|
|
44
|
+
|
|
45
|
+
## 5. 字体与颜色
|
|
46
|
+
|
|
47
|
+
- 不允许自定义 font-family 之外的特殊字体,系统字体最稳
|
|
48
|
+
- 正文字号 15-16px 为佳,行高 1.7-1.8,段间距 20-24px
|
|
49
|
+
- `text-align` **只允许 `left` / `center` / `right`**。`justify` 会被格式检测判为「非标准值」,
|
|
50
|
+
且部分安卓机型出现难看字间距 → 正文统一 `left`,标题与图注用 `center`
|
|
51
|
+
|
|
52
|
+
## 6. 表格
|
|
53
|
+
|
|
54
|
+
- 支持,但**列数 > 4 时在手机端必然横向溢出**
|
|
55
|
+
- 表头**不要** `white-space:nowrap`,它会强制撑宽导致溢出;改用 `word-break:break-word`
|
|
56
|
+
- **不要用 `table-layout:fixed`**(本条修正了此前的错误建议):
|
|
57
|
+
`fixed` 会让各列宽度**均分**,5 列表格在 677px 正文宽里每列只有 135px,
|
|
58
|
+
中文会被压成竖条。除非逐列显式设置百分比宽度,否则它只会让小屏更糟。
|
|
59
|
+
正确做法是让列宽按内容自适应(`table-layout:auto`,即不写)。
|
|
60
|
+
- **不用 `<thead>` / `<tbody>` / `<colgroup>`**:公众号不支持表格分组标签,
|
|
61
|
+
表头行直接作为首个 `<tr>` 输出
|
|
62
|
+
- **结论**(与 `md2wechat.py` 的实现一致):
|
|
63
|
+
- 列数 ≤ 3 → 保留 `<table>`,`width:100%` + 内容自适应
|
|
64
|
+
- 列数 ≥ 4 → **转卡片化**,每行一张卡(首列作标题,其余「列名 + 值」成对),
|
|
65
|
+
彻底摆脱横向溢出。这是唯一稳的解法。
|
|
66
|
+
|
|
67
|
+
## 7. 格式检测红线(实测触发告警的项)
|
|
68
|
+
|
|
69
|
+
微信侧/第三方格式检测会逐段校验内联样式,以下写法会被告警:
|
|
70
|
+
|
|
71
|
+
| 写法 | 告警 | 正确做法 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `text-align:justify` | 文字对齐异常·非标准值 | `text-align:left` |
|
|
74
|
+
| `max-width:677px` 等 px 宽度 | 不同屏幕下宽度差异 | `max-width:100%` |
|
|
75
|
+
| `<div>` 包裹 | 块被整段吞掉(样式全丢) | `<section>` |
|
|
76
|
+
| `<pre>` + `white-space:pre` | pre 标签·移动端溢出 | `<section>` + `pre-wrap` + `break-all` |
|
|
77
|
+
| `<h1>` 标签 | 标题语义映射,字号被覆盖 | `<p>` + 内联样式(20px/700/居中) |
|
|
78
|
+
| `<figure>` / `<figcaption>` | 粘贴时剥离包裹,图注错位 | `<section>` + `<p>` + 独立图注 |
|
|
79
|
+
| `<thead>` / `<tbody>` / `<colgroup>` | 表格分组标签不被支持 | 表头行直接作为首个 `<tr>` |
|
|
80
|
+
| `table-layout:fixed` | 列宽均分,小屏中文压成竖条 | 不写(按内容自适应)或逐列显式设宽 |
|
|
81
|
+
| `display:flex` / `grid` | 布局属性被吞,内容堆叠 | 用 `<section>` + `padding` 模拟 |
|
|
82
|
+
| `display:inline-block` | 非常规 display 值,支持不稳定 | 尽量用行内 `<span>` + padding |
|
|
83
|
+
| `float` / `position` | 定位失效,元素错位 | 不用定位,用块级流式布局 |
|
|
84
|
+
| `linear-gradient` | 渐变被静默丢弃,退化成无背景 | 纯色 `background` |
|
|
85
|
+
| `box-shadow` | 阴影被丢弃 | 不用阴影;层次靠底色 + 左边框 |
|
|
86
|
+
| `rgba()` / `hsla()` / `opacity` | 透明度不支持 | 纯色十六进制 |
|
|
87
|
+
| `-webkit-*` 私有属性 | 非标准属性 | 不用 |
|
|
88
|
+
| 表头 `white-space:nowrap` | 内容溢出 | `word-break:break-word` |
|
|
89
|
+
|
|
90
|
+
**圆角(`border-radius`)是「优雅降级」例外**:可能被丢弃,丢了只是变直角,
|
|
91
|
+
不破坏结构与可读性。可以用,但**不要依赖圆角做视觉区分**——卡片之间的区别必须
|
|
92
|
+
同时有底色或左边框,否则圆角一丢就分不清了。
|
|
93
|
+
|
|
94
|
+
**三样最可靠的手段**:纯色 `background` + `border-left` + 字号/颜色。
|
|
95
|
+
它们能覆盖 90% 的排版需求,且不会静默失效。
|
|
96
|
+
|
|
97
|
+
**本地预览页的宽度约束**要写进 `<head><style>`(粘进公众号时会被剥离),
|
|
98
|
+
正文内联样式始终保持百分比宽度——否则预览好看、粘贴后告警。
|
|
99
|
+
|
|
100
|
+
## 8. 粘贴方式
|
|
101
|
+
|
|
102
|
+
- 从浏览器复制渲染后的富文本,粘贴进编辑器可保留内联样式
|
|
103
|
+
- 直接粘贴 HTML 源码会被当成纯文本
|
|
104
|
+
- 不要用脚本直接注入剪贴板(`execCommand('copy')` 在预览页里可用,
|
|
105
|
+
但外部程序注入的 CF_HTML 微信识别率低,会退回纯文本)
|
|
106
|
+
- 推荐:本地 HTML 预览页 → 点「复制正文」或全选正文 → 复制 → 粘贴
|