Metadata-Version: 2.4
Name: wechat-article-checker
Version: 1.0.2
Summary: 微信公众号文章结构合规检测器：官方 verify-article-structure-spec 规则的独立前端实现（official/real 双口径行高叠字、font-family 白名单、text-align、复制污染、加粗斜体未生效）
Author: AladoooWu
License-Expression: MIT
Project-URL: Homepage, https://github.com/aladooo/wechat-article-checker
Project-URL: Repository, https://github.com/aladooo/wechat-article-checker
Project-URL: Issues, https://github.com/aladooo/wechat-article-checker/issues
Keywords: wechat,weixin,official-account,markdown,line-height,checker,typography
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: Chinese (Simplified)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Text Processing :: Markup
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# wechat-article-checker

<p align="center">
  <b>公众号文章结构合规检测器 —— 官方规则的独立前端实现，可在浏览器里复现「结构异常」弹窗</b>
</p>

<p align="center">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License"></a>
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="zero deps">
</p>

把一段**带内联样式的 HTML**（或一篇 Markdown + 宿主排版工具）交给本工具，它会生成一个探测页：用 Chrome 打开，按微信官方 [wechatjs/verify-article-structure-spec](https://github.com/wechatjs/verify-article-structure-spec) 的判定算法实测——**在粘贴进公众号之前**，预演出会不会弹「结构异常」警告。

> 本项目是 [aladooo/orangeink](https://github.com/aladooo/orangeink)（公众号 Markdown 排版台）内置自检器的命令行孪生版，两者互不依赖。规则对照的完整说明见 [docs/rules.md](docs/rules.md)。

## 为什么是浏览器，而不是纯脚本

官方的行高叠字检测依赖 **Range API 实测**（`getClientRects()` 矩形计数），纯 Node/Python 无法复现浏览器排版。所以本工具的形态是：**脚本生成探测页 → 浏览器打开 → 页面自动跑完并输出 JSON 报告**。

## 用法

### ① probe.py — 检测带内联样式的 HTML（推荐）

需要 Python 3，零第三方依赖。从 PyPI 安装（推荐）：

```bash
pip install wechat-article-checker
wechat-checker 你的文章.html -o _probe.html
```

或直接跑仓库脚本（无需安装）：

```bash
python python/probe.py 你的文章.html -o _probe.html
```

用 Chrome 打开生成的 `_probe.html`，约 1 秒后自动跑完，看页底 `<pre id="__probeReport">`（控制台同步打印同份 JSON）：

| 字段 | 含义 |
|------|------|
| `preview.count.lineHeight` | **official 口径**行高违规数——预测公众号会不会弹窗 |
| `preview.count.lineHeightReal` | **real 口径**真实叠字数——按行顶归并，official 误报时用它甄别 |
| `preview.count.fontFamily` | font-family 白名单违规数（官方仅允许 `mp-quote, PingFang SC, system-ui, -apple-system`） |
| `preview.count.textAlign` | `text-align:start/end` 残留数 |
| `preview.count.bareEmphasis` | **加粗/斜体未生效**——正文残留裸星号（`**` 紧贴中文标点开/收失败），含上下文与改法 |
| `payload.*` | 同一套检测跑在复制 payload 上，按 **585 / 677 / 375px** 三种宽度分别实测 |
| `payloadRaw.*` | 对 HTML 字符串本身的体检（无单位行高、浏览器复制污染属性等） |

也可以检查一篇 Markdown（渲染由宿主排版工具完成，目前支持 [orangeink](https://github.com/aladooo/orangeink) 类单文件编辑器）：

```bash
python python/probe.py 文章.md --host "排版工具.html" -o _probe.html
```

### ② verify.js — 渲染管线逻辑验证（Node）

验证 GFM 警告块识别、中英文加空格等 Markdown 渲染规则的实现正确性：

```bash
node js/verify.js                                # 用内置样例；vendor 解析见脚本头注释
node js/verify.js /path/to/markdown-it.min.js    # 显式指定 markdown-it 单文件
node js/verify.js "" 样例.md                     # 指定样例文件
```

也可从 npm 安装（全局命令 `wechat-article-checker`，等价于 `verify.js`）：

```bash
npm install -g wechat-article-checker
wechat-article-checker                # 跑内置渲染逻辑回归
```

全部 PASS 退出码为 0，任何 FAIL 为 1（可直接进 CI）。

### ③ 违规样例

[`examples/bad-sample.html`](examples/bad-sample.html) 是一段包含典型违规的最小样例（font-family 白名单、text-align:start、无单位行高）：

```bash
python python/probe.py examples/bad-sample.html -o _probe-bad.html
# 打开后应看到 fontFamily≥1、textAlign≥1、unitlessLineHeight≥1、bareEmphasis≥1
```

## 双口径说明

官方算法「矩形个数当行数」存在已知副作用：`getClientRects()` 对一行内的每个行内片段各返回一个矩形——段落里只要有一次加粗，矩形数就会大于真实行数，**单行纯文本段落被数学上无解地误判**。因此探测器对每个块同时输出：

- **official**——原样复刻官方算法，回答「公众号会不会弹窗」；
- **real**——按行顶部坐标归并出真实行数，回答「是否真的会叠字」。

official 报警而 real 无叠字 = 检测口径误报（上游工具可用「文本节点包裹」等结构策略规避，见 orangeink 的 `docs/self-check.md`）；real 也报 = 真问题，必须改行高。

## 与 orangeink 的关系

- [aladooo/orangeink](https://github.com/aladooo/orangeink) 内置了同一套规则的**编辑器内自检面板**（点「自检」即跑），适合写作时随手查；
- 本仓库是**独立探测页**形态，适合检查任何来源的 HTML（不限于 orangeink 的输出）；
- 两边代码独立维护，规则依据共享（[docs/rules.md](docs/rules.md)）。

## Roadmap

- **PyPI / npm 均已发布**：`pip install wechat-article-checker` 或 `npm install -g wechat-article-checker`；push `v*` 标签即双端自动构建发布（GitHub Actions OIDC Trusted Publishing，全程无 token，发布时 `pyproject.toml` 与 `package.json` 版本号需同步递增）；
- 违规样例截图库扩充中（[docs/images/](docs/images/)）；
- 更多规则的移植（当前覆盖：行高叠字双口径 / font-family 白名单 / text-align / 无单位行高 / 复制污染 / 加粗斜体未生效）。

遇到「自检全绿但公众号仍弹窗」的情况，欢迎开 issue 并附上可复现 payload——微信的黑盒行为一变，这里的对照表就该更新。

## License

[MIT](LICENSE)
