@lyhue1991/wxgzh 0.1.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.
Files changed (50) hide show
  1. package/README.md +432 -0
  2. package/assets/backgrounds//345/217/214/347/214/253.jpg +0 -0
  3. package/assets/backgrounds//345/217/244/351/243/216.jpg +0 -0
  4. package/assets/backgrounds//345/217/244/351/243/2162.jpg +0 -0
  5. package/assets/backgrounds//345/260/221/345/245/263/346/230/237/347/251/272.jpg +0 -0
  6. package/assets/backgrounds//345/277/203/345/277/203/347/233/270/345/215/260.jpg +0 -0
  7. package/assets/backgrounds//346/230/237/347/251/272.jpg +0 -0
  8. package/assets/backgrounds//346/240/221/346/234/250.jpg +0 -0
  9. package/assets/backgrounds//346/260/264/345/275/251.jpg +0 -0
  10. package/assets/backgrounds//346/260/264/346/274/253.jpg +0 -0
  11. package/assets/backgrounds//346/265/267/346/230/237.jpg +0 -0
  12. package/assets/backgrounds//346/265/267/346/273/251.jpg +0 -0
  13. package/assets/backgrounds//346/265/267/350/261/232.jpg +0 -0
  14. package/assets/backgrounds//346/270/205/346/231/250.jpg +0 -0
  15. package/assets/backgrounds//347/203/255/346/260/224/347/220/203.jpg +0 -0
  16. package/assets/backgrounds//347/214/253/345/222/252/345/245/263/345/255/251.jpg +0 -0
  17. package/assets/backgrounds//347/223/246/345/212/233.jpg +0 -0
  18. package/assets/backgrounds//347/272/242/345/217/266/351/243/230/351/243/230.jpg +0 -0
  19. package/assets/backgrounds//350/212/261/346/234/265.jpg +0 -0
  20. package/assets/backgrounds//351/243/216/350/275/246.jpg +0 -0
  21. package/assets/backgrounds//351/273/204/346/230/217.jpg +0 -0
  22. package/bin/wxgzh.js +3 -0
  23. package/dist/cli/config.js +62 -0
  24. package/dist/cli/cover.js +39 -0
  25. package/dist/cli/fix.js +38 -0
  26. package/dist/cli/index.js +161 -0
  27. package/dist/cli/md2html.js +49 -0
  28. package/dist/cli/publish.js +56 -0
  29. package/dist/core/converter.js +656 -0
  30. package/dist/core/cover.js +164 -0
  31. package/dist/core/fixer.js +97 -0
  32. package/dist/core/parser.js +105 -0
  33. package/dist/core/themes.js +59 -0
  34. package/dist/core/wechat.js +162 -0
  35. package/dist/types.js +2 -0
  36. package/dist/utils/config.js +89 -0
  37. package/dist/utils/fs.js +20 -0
  38. package/dist/utils/logger.js +18 -0
  39. package/dist/utils/tls.js +46 -0
  40. package/package.json +47 -0
  41. package/spec.md +490 -0
  42. package/styles/black.css +600 -0
  43. package/styles/blue.css +616 -0
  44. package/styles/brown.css +620 -0
  45. package/styles/custom.css +8 -0
  46. package/styles/default.css +227 -0
  47. package/styles/green.css +617 -0
  48. package/styles/orange.css +617 -0
  49. package/styles/red.css +617 -0
  50. package/styles/yellow.css +202 -0
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ensureParentDir = ensureParentDir;
7
+ exports.writeTextFile = writeTextFile;
8
+ exports.readTextFile = readTextFile;
9
+ const promises_1 = require("node:fs/promises");
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ async function ensureParentDir(filePath) {
12
+ await (0, promises_1.mkdir)(node_path_1.default.dirname(filePath), { recursive: true });
13
+ }
14
+ async function writeTextFile(filePath, content) {
15
+ await ensureParentDir(filePath);
16
+ await (0, promises_1.writeFile)(filePath, content, 'utf8');
17
+ }
18
+ async function readTextFile(filePath) {
19
+ return (0, promises_1.readFile)(filePath, 'utf8');
20
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.info = info;
4
+ exports.success = success;
5
+ exports.warn = warn;
6
+ exports.error = error;
7
+ function info(message) {
8
+ console.log(`ℹ ${message}`);
9
+ }
10
+ function success(message) {
11
+ console.log(`✅ ${message}`);
12
+ }
13
+ function warn(message) {
14
+ console.warn(`⚠ ${message}`);
15
+ }
16
+ function error(message) {
17
+ throw new Error(message);
18
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getHttpsAgent = getHttpsAgent;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const node_fs_1 = require("node:fs");
9
+ const node_https_1 = __importDefault(require("node:https"));
10
+ const node_tls_1 = __importDefault(require("node:tls"));
11
+ let cachedAgent;
12
+ function readMacCertificates() {
13
+ const keychains = [
14
+ '/System/Library/Keychains/SystemRootCertificates.keychain',
15
+ '/Library/Keychains/System.keychain'
16
+ ].filter((filePath) => (0, node_fs_1.existsSync)(filePath));
17
+ const certificates = [];
18
+ for (const keychain of keychains) {
19
+ try {
20
+ const output = (0, node_child_process_1.execFileSync)('security', ['find-certificate', '-a', '-p', keychain], {
21
+ encoding: 'utf8'
22
+ });
23
+ if (output.trim()) {
24
+ certificates.push(output);
25
+ }
26
+ }
27
+ catch {
28
+ // 读取系统钥匙串失败时退回 Node 内置证书。
29
+ }
30
+ }
31
+ return certificates;
32
+ }
33
+ function getHttpsAgent() {
34
+ if (cachedAgent) {
35
+ return cachedAgent;
36
+ }
37
+ const ca = [...node_tls_1.default.rootCertificates];
38
+ if (process.platform === 'darwin') {
39
+ ca.push(...readMacCertificates());
40
+ }
41
+ cachedAgent = new node_https_1.default.Agent({
42
+ ca,
43
+ keepAlive: true
44
+ });
45
+ return cachedAgent;
46
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@lyhue1991/wxgzh",
3
+ "version": "0.1.0",
4
+ "description": "Markdown to WeChat Official Account draft CLI",
5
+ "license": "MIT",
6
+ "main": "dist/cli/index.js",
7
+ "bin": {
8
+ "wxgzh": "bin/wxgzh.js"
9
+ },
10
+ "files": [
11
+ "bin",
12
+ "dist",
13
+ "assets",
14
+ "styles",
15
+ "spec.md"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json",
22
+ "typecheck": "tsc -p tsconfig.json --noEmit",
23
+ "prepare": "npm run build"
24
+ },
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "dependencies": {
29
+ "axios": "^1.8.4",
30
+ "cheerio": "^1.0.0",
31
+ "commander": "^14.0.1",
32
+ "dotenv": "^16.4.7",
33
+ "form-data": "^4.0.2",
34
+ "gray-matter": "^4.0.3",
35
+ "highlight.js": "^11.11.1",
36
+ "juice": "^11.1.1",
37
+ "markdown-it": "^14.1.0",
38
+ "markdown-it-mathjax3": "^5.2.0",
39
+ "mathjax": "^4.1.1",
40
+ "sharp": "^0.33.5"
41
+ },
42
+ "devDependencies": {
43
+ "@types/markdown-it": "^14.1.2",
44
+ "@types/node": "^22.13.14",
45
+ "typescript": "^5.8.2"
46
+ }
47
+ }
package/spec.md ADDED
@@ -0,0 +1,490 @@
1
+ # wxgzh 规格说明
2
+
3
+ ## 项目概述
4
+
5
+ `wxgzh` 是一个基于 Node.js + TypeScript 的命令行工具,用于把 Markdown 文章处理成微信公众号草稿。
6
+
7
+ 当前已实现能力:
8
+
9
+ - Markdown 解析与 front matter 元数据提取。
10
+ - 主题 CSS 内联,生成适合微信公众号编辑器的 HTML。
11
+ - 修复正文中的图片与不兼容结构,并可上传正文图片到微信。
12
+ - 基于内置背景图或自定义背景图生成封面。
13
+ - 上传封面并创建微信公众号草稿。
14
+ - 提供一键流程:`md2html -> fix -> cover -> publish`。
15
+
16
+ ---
17
+
18
+ ## 运行环境
19
+
20
+ - Node.js >= 18
21
+ - 包管理器:`npm`
22
+ - 编译命令:`npm run build`
23
+ - 类型检查:`npm run typecheck`
24
+
25
+ ---
26
+
27
+ ## 命令设计
28
+
29
+ ### 1. 根命令
30
+
31
+ ```bash
32
+ wxgzh [article.md] [options]
33
+ ```
34
+
35
+ 传入 Markdown 文件后,会自动执行完整流程:
36
+
37
+ 1. 转换 Markdown 为 HTML
38
+ 2. 修复 HTML 并上传正文图片
39
+ 3. 生成或使用现成封面
40
+ 4. 发布为微信公众号草稿
41
+
42
+ 支持参数:
43
+
44
+ - `--theme <theme>`:覆盖主题名
45
+ - `--author <author>`:覆盖作者名
46
+ - `--cover <cover.jpg>`:指定现成封面图
47
+ - `--no-cover`:禁用自动生成封面
48
+ - `--digest <digest>`:覆盖摘要
49
+ - `--output-dir <dir>`:指定中间产物输出目录
50
+ - `--enable-comment`:为本次草稿开启评论
51
+
52
+ 示例:
53
+
54
+ ```bash
55
+ wxgzh article.md
56
+ wxgzh article.md --theme blue
57
+ wxgzh article.md --author "wxgzh" --digest "这是一篇摘要"
58
+ wxgzh article.md --cover ./cover.jpg
59
+ wxgzh article.md --no-cover
60
+ ```
61
+
62
+ 说明:
63
+
64
+ - 默认中间产物目录为文章同级的 `.wxgzh/`。
65
+ - 若未传 `--cover` 且未指定 `--no-cover`,会自动生成简易封面。
66
+ - 根命令会直接调用微信接口,因此要求已配置 `appid` 与 `appsecret`。
67
+
68
+ ---
69
+
70
+ ### 2. `config`
71
+
72
+ ```bash
73
+ wxgzh config [options]
74
+ ```
75
+
76
+ 用于查看或更新用户级默认配置。
77
+
78
+ 支持参数:
79
+
80
+ - `--appid <appid>`:设置微信公众号 appid
81
+ - `--appsecret <appsecret>`:设置微信公众号 appsecret
82
+ - `--author <author>`:设置默认作者名
83
+ - `--default-theme <theme>`:设置默认主题
84
+ - `--enable-comment`:默认开启评论
85
+ - `--disable-comment`:默认关闭评论
86
+ - `--list`:查看当前生效配置
87
+ - `--list-themes`:列出可用主题
88
+ - `--clear`:清空用户级配置文件
89
+
90
+ 示例:
91
+
92
+ ```bash
93
+ wxgzh config --list
94
+ wxgzh config --list-themes
95
+ wxgzh config --author "wxgzh" --default-theme blue
96
+ wxgzh config --enable-comment
97
+ ```
98
+
99
+ 说明:
100
+
101
+ - 用户级配置文件路径为 `~/.config/wxgzh/wxgzh.json`。
102
+ - 当前未实现项目级配置文件。
103
+ - 环境变量仅支持 `WX_APPID`、`WX_APPSECRET`。
104
+
105
+ ---
106
+
107
+ ### 3. `md2html`
108
+
109
+ ```bash
110
+ wxgzh md2html --from <input.md> --to <output.html> [options]
111
+ ```
112
+
113
+ 把 Markdown 转换为带内联样式前原始结构的 HTML,并写入元数据。
114
+
115
+ 支持参数:
116
+
117
+ - `--from <input.md>`:输入 Markdown 文件路径
118
+ - `--to <output.html>`:输出 HTML 文件路径
119
+ - `--theme <theme>`:覆盖主题名
120
+ - `--author <author>`:覆盖作者名
121
+
122
+ 示例:
123
+
124
+ ```bash
125
+ wxgzh md2html --from article.md --to .wxgzh/article.html
126
+ wxgzh md2html --from article.md --to .wxgzh/article.html --theme blue
127
+ ```
128
+
129
+ 说明:
130
+
131
+ - 支持 front matter:`title`、`author`、`digest`、`theme`、`cover`、`enableComment`。
132
+ - 若 front matter 中未设置 `title`,会尝试使用正文第一个一级标题。
133
+ - 若 front matter 中未设置 `digest`,会优先使用二级标题拼接生成摘要,兜底为标题或默认摘要。
134
+ - 会记录源 Markdown 所在目录,用于后续解析相对图片路径。
135
+
136
+ ---
137
+
138
+ ### 4. `fix`
139
+
140
+ ```bash
141
+ wxgzh fix <article.html> [options]
142
+ ```
143
+
144
+ 修复 HTML 中的图片与不兼容结构,并按需上传正文图片。
145
+
146
+ 支持参数:
147
+
148
+ - `--no-upload`:只修复 HTML,不上传图片
149
+ - `--cdn <url>`:把本地图片路径替换为指定 CDN 地址
150
+
151
+ 示例:
152
+
153
+ ```bash
154
+ wxgzh fix .wxgzh/article.html
155
+ wxgzh fix .wxgzh/article.html --no-upload
156
+ wxgzh fix .wxgzh/article.html --cdn https://cdn.example.com
157
+ ```
158
+
159
+ 当前行为:
160
+
161
+ - 移除 `<script>`、`<iframe>` 标签。
162
+ - 为图片补充适合微信正文的内联样式。
163
+ - 若开启上传,会把非微信 CDN 图片上传到微信素材接口。
164
+ - 若指定 `--cdn` 且未上传,则把本地图片替换为 CDN 地址。
165
+
166
+ ---
167
+
168
+ ### 5. `cover`
169
+
170
+ ```bash
171
+ wxgzh cover [options]
172
+ ```
173
+
174
+ 生成公众号封面图。
175
+
176
+ 支持参数:
177
+
178
+ - `--background <pic.jpg>`:指定自定义背景图
179
+ - `--title <title>`:封面标题
180
+ - `--author <author>`:作者名
181
+ - `--to <cover.jpg>`:输出文件路径
182
+ - `--list`:列出全部内置背景图名称
183
+
184
+ 示例:
185
+
186
+ ```bash
187
+ wxgzh cover --list
188
+ wxgzh cover --title "我的文章" --to .wxgzh/cover.jpg
189
+ wxgzh cover --title "我的文章" --background ./bg.jpg --to .wxgzh/cover.jpg
190
+ ```
191
+
192
+ 说明:
193
+
194
+ - 未指定 `--background` 时,会自动随机选取 `assets/backgrounds/` 中的内置背景图。
195
+ - 若内置背景图目录为空,则退化为渐变底色封面。
196
+ - 当前封面生成基于 `sharp` + SVG 叠字实现,不依赖 `canvas` 或本地字体目录。
197
+
198
+ ---
199
+
200
+ ### 6. `publish`
201
+
202
+ ```bash
203
+ wxgzh publish --article <article.html> --cover <cover.jpg> [options]
204
+ ```
205
+
206
+ 把 HTML 正文与封面图提交到微信公众号草稿箱。
207
+
208
+ 支持参数:
209
+
210
+ - `--article <article.html>`:正文 HTML 路径
211
+ - `--cover <cover.jpg>`:封面图路径
212
+ - `--title <title>`:覆盖标题
213
+ - `--author <author>`:覆盖作者名
214
+ - `--digest <digest>`:覆盖摘要
215
+ - `--enable-comment`:开启评论
216
+
217
+ 示例:
218
+
219
+ ```bash
220
+ wxgzh publish --article .wxgzh/article.html --cover .wxgzh/cover.jpg
221
+ wxgzh publish --article .wxgzh/article.html --cover .wxgzh/cover.jpg --title "新的标题"
222
+ ```
223
+
224
+ 说明:
225
+
226
+ - 会先上传封面图,再创建草稿。
227
+ - 标题、作者、摘要、评论开关都支持命令参数覆盖 HTML 元数据与默认配置。
228
+
229
+ ---
230
+
231
+ ### 7. `examples`
232
+
233
+ ```bash
234
+ wxgzh examples
235
+ ```
236
+
237
+ 打印常用示例命令。
238
+
239
+ ---
240
+
241
+ ## Front Matter
242
+
243
+ 当前支持的 front matter 字段:
244
+
245
+ ```yaml
246
+ ---
247
+ title: 我的文章标题
248
+ author: wxgzh
249
+ digest: 文章摘要
250
+ theme: default
251
+ cover: ./cover.jpg
252
+ enableComment: true
253
+ ---
254
+ ```
255
+
256
+ 字段说明:
257
+
258
+ - `title`:文章标题
259
+ - `author`:作者名
260
+ - `digest`:摘要
261
+ - `theme`:主题名
262
+ - `cover`:封面图相对或绝对路径
263
+ - `enableComment`:是否开启评论
264
+
265
+ ---
266
+
267
+ ## 配置文件
268
+
269
+ 用户级配置文件路径:
270
+
271
+ ```text
272
+ ~/.config/wxgzh/wxgzh.json
273
+ ```
274
+
275
+ 配置格式:
276
+
277
+ ```json
278
+ {
279
+ "appid": "wx1234567890abcdef",
280
+ "appsecret": "1234567890abcdef1234567890abcdef",
281
+ "author": "wxgzh",
282
+ "defaultTheme": "default",
283
+ "enableComment": true
284
+ }
285
+ ```
286
+
287
+ 环境变量:
288
+
289
+ - `WX_APPID`
290
+ - `WX_APPSECRET`
291
+
292
+ 说明:
293
+
294
+ - `config --list` 输出的是当前生效配置。
295
+ - `appsecret` 在输出时会自动脱敏。
296
+ - 微信 access token 会额外缓存到 `~/.config/wxgzh/token.<appid>.json`。
297
+
298
+ ---
299
+
300
+ ## 技术栈
301
+
302
+ ### 运行时依赖
303
+
304
+ | 包名 | 用途 |
305
+ |------|------|
306
+ | `axios` | 微信接口与远程资源请求 |
307
+ | `cheerio` | HTML 结构处理 |
308
+ | `commander` | CLI 框架 |
309
+ | `dotenv` | 环境变量加载 |
310
+ | `form-data` | 上传微信素材 |
311
+ | `gray-matter` | front matter 解析 |
312
+ | `highlight.js` | 代码高亮 |
313
+ | `juice` | CSS 内联 |
314
+ | `markdown-it` | Markdown 渲染 |
315
+ | `markdown-it-mathjax3` | 数学公式渲染 |
316
+ | `mathjax` | MathJax 支持 |
317
+ | `sharp` | 封面图生成 |
318
+
319
+ ### 开发依赖
320
+
321
+ | 包名 | 用途 |
322
+ |------|------|
323
+ | `typescript` | TypeScript 编译 |
324
+ | `@types/node` | Node.js 类型定义 |
325
+ | `@types/markdown-it` | MarkdownIt 类型定义 |
326
+
327
+ 说明:
328
+
329
+ - 当前仓库未接入 Jest、Vitest 等测试框架。
330
+ - 当前仓库未配置 ESLint。
331
+
332
+ ---
333
+
334
+ ## 项目结构
335
+
336
+ ```text
337
+ wxgzh/
338
+ ├── AGENTS.md
339
+ ├── assets/
340
+ │ └── backgrounds/ # 内置封面背景图
341
+ ├── bin/
342
+ │ └── wxgzh.js # CLI 启动入口
343
+ ├── dist/ # 编译产物
344
+ ├── src/
345
+ │ ├── cli/
346
+ │ │ ├── config.ts # config 命令
347
+ │ │ ├── cover.ts # cover 命令
348
+ │ │ ├── fix.ts # fix 命令
349
+ │ │ ├── index.ts # 根命令与子命令注册
350
+ │ │ ├── md2html.ts # md2html 命令
351
+ │ │ └── publish.ts # publish 命令
352
+ │ ├── core/
353
+ │ │ ├── converter.ts # Markdown -> HTML 与样式内联
354
+ │ │ ├── cover.ts # 封面图生成
355
+ │ │ ├── fixer.ts # HTML 修复与图片处理
356
+ │ │ ├── parser.ts # Markdown 与 front matter 解析
357
+ │ │ ├── themes.ts # 主题发现与校验
358
+ │ │ └── wechat.ts # 微信 API 封装
359
+ │ ├── types/
360
+ │ │ └── markdown-it-mathjax3.d.ts
361
+ │ ├── types.ts # 共享类型定义
362
+ │ └── utils/
363
+ │ ├── config.ts # 用户配置管理
364
+ │ ├── fs.ts # 文件工具
365
+ │ ├── logger.ts # 日志输出
366
+ │ └── tls.ts # TLS 兼容处理
367
+ ├── styles/
368
+ │ ├── default.css # 默认主题
369
+ │ ├── custom.css # 自定义覆盖样式
370
+ │ ├── blue.css # 其他主题
371
+ │ ├── black.css
372
+ │ ├── brown.css
373
+ │ ├── green.css
374
+ │ ├── orange.css
375
+ │ ├── red.css
376
+ │ └── yellow.css
377
+ ├── package.json
378
+ ├── package-lock.json
379
+ ├── spec.md
380
+ ├── test_article1.md
381
+ ├── test_article2.md
382
+ └── tsconfig.json
383
+ ```
384
+
385
+ ---
386
+
387
+ ## 微信接口
388
+
389
+ 当前实际使用的微信接口如下。
390
+
391
+ ### 1. 获取 Access Token
392
+
393
+ ```http
394
+ GET https://api.weixin.qq.com/cgi-bin/token
395
+ ```
396
+
397
+ 查询参数:
398
+
399
+ - `grant_type=client_credential`
400
+ - `appid=<APPID>`
401
+ - `secret=<APPSECRET>`
402
+
403
+ ### 2. 上传正文图片
404
+
405
+ ```http
406
+ POST https://api.weixin.qq.com/cgi-bin/media/uploadimg
407
+ ```
408
+
409
+ ### 3. 上传封面图
410
+
411
+ ```http
412
+ POST https://api.weixin.qq.com/cgi-bin/material/add_material
413
+ ```
414
+
415
+ 查询参数:
416
+
417
+ - `type=thumb`
418
+
419
+ ### 4. 创建草稿
420
+
421
+ ```http
422
+ POST https://api.weixin.qq.com/cgi-bin/draft/add
423
+ ```
424
+
425
+ 请求体核心字段:
426
+
427
+ ```json
428
+ {
429
+ "articles": [
430
+ {
431
+ "title": "标题",
432
+ "author": "作者",
433
+ "digest": "摘要",
434
+ "content": "HTML 内容",
435
+ "thumb_media_id": "封面 media_id",
436
+ "need_open_comment": 1,
437
+ "only_fans_can_comment": 0
438
+ }
439
+ ]
440
+ }
441
+ ```
442
+
443
+ ---
444
+
445
+ ## 当前行为说明
446
+
447
+ ### HTML 处理
448
+
449
+ - 使用 `markdown-it` 渲染 Markdown。
450
+ - 使用 `highlight.js` 处理代码块高亮。
451
+ - 使用 `markdown-it-mathjax3` + `mathjax` 处理数学公式。
452
+ - 使用 `juice` 把主题 CSS 与补充样式内联到最终 HTML。
453
+ - 会标准化图片、表格、引用块等结构,以适配微信公众号。
454
+
455
+ ### 图片处理
456
+
457
+ - 支持本地图片与远程图片。
458
+ - 相对图片路径会基于源 Markdown 所在目录解析。
459
+ - 正文图片上传后会替换为微信返回的 CDN 地址。
460
+
461
+ ### 封面生成
462
+
463
+ - 优先使用命令行传入的背景图。
464
+ - 未传背景图时,从 `assets/backgrounds/` 中随机选择。
465
+ - 若没有可用背景图,使用内置渐变背景兜底。
466
+
467
+ ---
468
+
469
+ ## 已知限制
470
+
471
+ - 当前没有项目级配置文件,仅支持用户级配置和部分环境变量。
472
+ - 当前未接入自动化测试框架。
473
+ - 当前未接入 ESLint。
474
+ - 当前未实现 Mermaid 专用渲染,Mermaid 代码块会按普通代码块处理。
475
+ - 微信平台对外链、HTML 标签和样式能力本身仍有限制,最终展示以平台实际效果为准。
476
+
477
+ ---
478
+
479
+ ## 常用验证命令
480
+
481
+ ```bash
482
+ npm run typecheck
483
+ npm run build
484
+ node dist/cli/index.js --help
485
+ node dist/cli/index.js config --help
486
+ node dist/cli/index.js md2html --help
487
+ node dist/cli/index.js fix --help
488
+ node dist/cli/index.js cover --help
489
+ node dist/cli/index.js publish --help
490
+ ```