@zzclub/pipeline 0.2.0 → 0.4.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/README.md +366 -170
- package/package.json +4 -7
- package/src/adapter-loader.ts +138 -0
- package/src/adapter-types.ts +172 -0
- package/src/adapters/builtin-image-renderer.ts +353 -0
- package/src/adapters/builtin-markdown-renderer.ts +63 -0
- package/src/adapters/index.ts +2 -0
- package/src/args.test.ts +118 -0
- package/src/args.ts +90 -0
- package/src/cli.ts +51 -0
- package/src/commands/abandon.test.ts +104 -0
- package/src/commands/abandon.ts +202 -0
- package/src/commands/attach-body-images.ts +88 -0
- package/src/commands/attach-body.ts +86 -0
- package/src/commands/attach-newspic-spec.ts +41 -0
- package/src/commands/checkpoint.test.ts +91 -0
- package/src/commands/checkpoint.ts +66 -0
- package/src/commands/config.ts +106 -0
- package/src/commands/cos-upload.ts +62 -0
- package/src/commands/doctor.ts +66 -0
- package/src/commands/find-run.ts +55 -0
- package/src/commands/hermes-metrics.ts +226 -0
- package/src/commands/imgx.ts +60 -0
- package/src/commands/ingest-handoff.ts +509 -0
- package/src/commands/init.ts +126 -0
- package/src/commands/prepare-finalize.ts +348 -0
- package/src/commands/prepare.ts +310 -0
- package/src/commands/publish.ts +147 -0
- package/src/commands/reconcile.ts +36 -0
- package/src/commands/render.ts +244 -0
- package/src/commands/reset.test.ts +151 -0
- package/src/commands/reset.ts +159 -0
- package/src/commands/review.ts +77 -0
- package/src/commands/status.ts +68 -0
- package/src/commands/sync-blog.ts +39 -0
- package/src/commands/tasks.ts +50 -0
- package/src/commands/wechat-export.ts +68 -0
- package/src/config.ts +0 -0
- package/src/imgx/ascii-portrait.ts +77 -0
- package/src/imgx/assets/fonts/AlimamaShuHeiTi-Bold.ttf +0 -0
- package/src/imgx/assets/fonts/LXGWNeoZhiSongPlus.ttf +0 -0
- package/src/imgx/assets/fonts/LXGWWenKai-Regular.ttf +0 -0
- package/src/imgx/assets/icons/logo.png +0 -0
- package/src/imgx/assets/icons/logo.svg +8 -0
- package/{dist/assets → src}/imgx/assets/templates/longform-3-4.html +1 -1
- package/{dist/assets → src}/imgx/assets/templates/poster-3-4.html +69 -30
- package/{dist/assets → src}/imgx/assets/templates/wechat-cover-split.html +58 -27
- package/src/imgx/cli.ts +57 -0
- package/src/imgx/geometry.ts +68 -0
- package/src/imgx/index.ts +5 -0
- package/src/imgx/longform-theme.ts +243 -0
- package/src/imgx/poster-recipe.ts +81 -0
- package/src/imgx/pretext-adapter.ts +14 -0
- package/src/imgx/pretext-runtime.ts +61 -0
- package/src/imgx/references/ascii-portrait-3-4.md +59 -0
- package/src/imgx/references/longform-3-4.md +173 -0
- package/src/imgx/references/poster-3-4.md +87 -0
- package/src/imgx/references/tips-3-4.md +69 -0
- package/src/imgx/references/wechat-cover-split.md +89 -0
- package/src/imgx/references/x-like-posts.md +139 -0
- package/src/imgx/render-article.test.ts +53 -0
- package/src/imgx/render-article.ts +1364 -0
- package/src/imgx/render-ascii-portrait.ts +53 -0
- package/src/imgx/render-card.ts +232 -0
- package/src/imgx/render-x-like-posts.ts +235 -0
- package/src/imgx/runtime.ts +403 -0
- package/src/imgx/typographic-scale.test.ts +56 -0
- package/src/imgx/typographic-scale.ts +44 -0
- package/src/output.ts +632 -0
- package/src/plugins.ts +101 -0
- package/src/profiles.ts +149 -0
- package/src/providers/blog.test.ts +58 -0
- package/src/providers/blog.ts +154 -0
- package/src/providers/cos.ts +183 -0
- package/src/providers/index.test.ts +26 -0
- package/src/providers/index.ts +185 -0
- package/src/providers/wechat.test.ts +215 -0
- package/src/providers/wechat.ts +548 -0
- package/src/routes.ts +287 -0
- package/src/runtime-paths.ts +179 -0
- package/src/schema/config.ts +133 -0
- package/src/schema/state.ts +376 -0
- package/src/spawn.ts +103 -0
- package/src/state.ts +265 -0
- package/src/task-manager.ts +657 -0
- package/src/task-views.ts +222 -0
- package/src/text.test.ts +689 -0
- package/src/text.ts +683 -0
- package/src/wechat-preview/assets/fonts/SweiCurveLegCJKsc-Regular.woff +0 -0
- package/src/wechat-preview/browser/editor-export.css +241 -0
- package/src/wechat-preview/browser/editor-export.ts +103 -0
- package/src/wechat-preview/frontmatter-handler.ts +73 -0
- package/src/wechat-preview/index.test.ts +154 -0
- package/src/wechat-preview/index.ts +294 -0
- package/src/wechat-preview/themes.ts +141 -0
- package/src/wechat-preview/wechat-formatter.test.ts +288 -0
- package/src/wechat-preview/wechat-formatter.ts +1506 -0
- package/src/wechat-preview.test.ts +73 -0
- package/src/workflow-materials.test.ts +225 -0
- package/src/workflow-materials.ts +217 -0
- package/src/workflow.test.ts +2087 -0
- package/dist/assets/imgx/assets/icons/avatar_jinx_cartoon.jpg +0 -0
- package/dist/assets/imgx/assets/icons/fishbone-logo-square.png +0 -0
- package/dist/assets/imgx/assets/icons/fishbone-logo.jpg +0 -0
- package/dist/assets/imgx/assets/icons/fishbone-logo.png +0 -0
- package/dist/assets/imgx/assets/icons/openclaw-logo.svg +0 -22
- package/dist/assets/imgx/assets/icons/zzclub-logo-black.jpg +0 -0
- package/dist/assets/imgx/assets/icons/zzclub-logo-gray.svg +0 -25
- package/dist/cli.js +0 -432
- package/dist/node_modules/@chenglou/pretext/dist/analysis.d.ts +0 -33
- package/dist/node_modules/@chenglou/pretext/dist/analysis.js +0 -1063
- package/dist/node_modules/@chenglou/pretext/dist/bidi.d.ts +0 -1
- package/dist/node_modules/@chenglou/pretext/dist/bidi.js +0 -175
- package/dist/node_modules/@chenglou/pretext/dist/generated/bidi-data.d.ts +0 -4
- package/dist/node_modules/@chenglou/pretext/dist/generated/bidi-data.js +0 -979
- package/dist/node_modules/@chenglou/pretext/dist/layout.d.ts +0 -70
- package/dist/node_modules/@chenglou/pretext/dist/layout.js +0 -496
- package/dist/node_modules/@chenglou/pretext/dist/line-break.d.ts +0 -36
- package/dist/node_modules/@chenglou/pretext/dist/line-break.js +0 -820
- package/dist/node_modules/@chenglou/pretext/dist/measurement.d.ts +0 -28
- package/dist/node_modules/@chenglou/pretext/dist/measurement.js +0 -219
- package/dist/node_modules/@chenglou/pretext/dist/rich-inline.d.ts +0 -51
- package/dist/node_modules/@chenglou/pretext/dist/rich-inline.js +0 -401
- /package/{dist/assets → src}/imgx/assets/browser/obstacle-flow.d.ts +0 -0
- /package/{dist/assets → src}/imgx/assets/browser/obstacle-flow.js +0 -0
- /package/{dist/assets → src}/imgx/assets/icons/clover.svg +0 -0
- /package/{dist/assets → src}/imgx/assets/templates/ascii-portrait-3-4.html +0 -0
- /package/{dist/assets → src}/imgx/assets/templates/ascii-portrait-tile.html +0 -0
- /package/{dist/assets → src}/imgx/assets/templates/tips-3-4.html +0 -0
- /package/{dist/assets → src}/imgx/assets/templates/x-like-posts.html +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/.vite/manifest.json +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/SweiCurveLegCJKsc-Regular-B3Ut5bwH.woff +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/assets/style-BYNXnUvc.css +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/browser-dist/editor-export.js +0 -0
- /package/{dist/assets → src}/wechat-preview/assets/templates/export-shell.html +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# x-like-posts 模板规范
|
|
2
|
+
|
|
3
|
+
比例:自适应长图 | 宽度:900px | 用途:将多条帖子整理成一张 X / Twitter 风格分享长图
|
|
4
|
+
|
|
5
|
+
## 适用场景
|
|
6
|
+
|
|
7
|
+
- 用户要“X 风格分享图”
|
|
8
|
+
- 用户给的是帖子类型数据,不一定来自 Twitter
|
|
9
|
+
- 用户希望保留 X 的阅读感,但以通用帖子分享图方式导出
|
|
10
|
+
|
|
11
|
+
## 渲染命令
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun ./scripts/render-x-like-posts.ts \
|
|
15
|
+
--author "OpenAI" \
|
|
16
|
+
--handle "@OpenAI" \
|
|
17
|
+
--post "第一条帖子内容" \
|
|
18
|
+
--post "第二条帖子内容" \
|
|
19
|
+
--out tmp/x-like-posts.png
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
如帖子较多,优先写入 JSON 文件后传入:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bun ./scripts/render-x-like-posts.ts \
|
|
26
|
+
--author "OpenAI" \
|
|
27
|
+
--handle "@OpenAI" \
|
|
28
|
+
--posts-file tmp/posts.json \
|
|
29
|
+
--out /absolute/path/to/output/x-like-posts.png
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## JSON 输入格式
|
|
33
|
+
|
|
34
|
+
`--posts-file` 读取一个 JSON 数组,支持两种结构。
|
|
35
|
+
|
|
36
|
+
### 1. 字符串数组
|
|
37
|
+
|
|
38
|
+
最简格式,每个元素只提供正文:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
[
|
|
42
|
+
"post 1",
|
|
43
|
+
"post 2"
|
|
44
|
+
]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
此格式下模板只显示:
|
|
48
|
+
|
|
49
|
+
- 正文
|
|
50
|
+
- 外层参数提供的作者名 / handle / avatar
|
|
51
|
+
|
|
52
|
+
### 2. 对象数组
|
|
53
|
+
|
|
54
|
+
推荐格式,每条帖子可带时间和互动信息:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
[
|
|
58
|
+
{
|
|
59
|
+
"text": "post 1",
|
|
60
|
+
"created_at": "2026-03-11T04:39:46.000Z",
|
|
61
|
+
"url": "https://x.com/foo/status/1",
|
|
62
|
+
"favorite_count": 31,
|
|
63
|
+
"retweet_count": 4
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"text": "post 2"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
字段规则:
|
|
72
|
+
|
|
73
|
+
| 字段 | 必填 | 说明 | 当前是否显示 |
|
|
74
|
+
|------|------|------|--------------|
|
|
75
|
+
| `text` | 是 | 帖子正文 | 是 |
|
|
76
|
+
| `created_at` | 否 | 帖子发布时间,建议 ISO 8601 | 是 |
|
|
77
|
+
| `url` | 否 | 原帖链接 | 是(显示为 `x.com` 标记) |
|
|
78
|
+
| `favorite_count` | 否 | 点赞数 | 是 |
|
|
79
|
+
| `retweet_count` | 否 | 转发 / repost 数 | 是 |
|
|
80
|
+
|
|
81
|
+
### 当前模板显示逻辑
|
|
82
|
+
|
|
83
|
+
- `text`:显示为正文
|
|
84
|
+
- `created_at`:显示在每条帖子底部,并用于顶部日期标签
|
|
85
|
+
- `favorite_count`:大于 0 时显示
|
|
86
|
+
- `retweet_count`:大于 0 时显示
|
|
87
|
+
- `url`:存在时显示 `x.com` 来源标记
|
|
88
|
+
- 作者名、handle、avatar:不从 JSON 内层读取,而是由外层参数 `--author`、`--handle`、`--avatar` 控制
|
|
89
|
+
|
|
90
|
+
### 输入兼容说明
|
|
91
|
+
|
|
92
|
+
- 旧参数 `--tweet` / `--tweets-file` 仍可用
|
|
93
|
+
- 如果输入来自 `ingest-service`,优先使用它的 `created_at` 作为发布时间
|
|
94
|
+
|
|
95
|
+
## 参数说明
|
|
96
|
+
|
|
97
|
+
| 参数 | 默认值 | 说明 |
|
|
98
|
+
|------|--------|------|
|
|
99
|
+
| `--author` | `Unknown Author` | 作者名 |
|
|
100
|
+
| `--handle` | `@twitter` | 作者 handle |
|
|
101
|
+
| `--post` | 空 | 单条帖子内容,可重复传多次 |
|
|
102
|
+
| `--posts-file` | 空 | 帖子 JSON 文件 |
|
|
103
|
+
| `--out` | 必填 | 输出 PNG 路径,支持相对路径或绝对路径 |
|
|
104
|
+
| `--header-label` | `X-like 帖子分享图` | 顶部说明文案 |
|
|
105
|
+
| `--footer` | `整理转发 · via zzhub-media-imgx` | 底部来源文案 |
|
|
106
|
+
| `--bg` | `#f5f8fa` | 页面背景 |
|
|
107
|
+
| `--card-bg` | `#ffffff` | 卡片背景 |
|
|
108
|
+
| `--text` | `#0f1419` | 正文颜色 |
|
|
109
|
+
| `--muted` | `#536471` | 次级文字颜色 |
|
|
110
|
+
| `--border` | `#e6ecf0` | 分隔线颜色 |
|
|
111
|
+
| `--accent` | `#1d9bf0` | 强调色 |
|
|
112
|
+
| `--avatar` | 默认头像 | 作者头像 |
|
|
113
|
+
|
|
114
|
+
## 内容处理规则
|
|
115
|
+
|
|
116
|
+
1. 一条帖子对应一个卡片区块,按输入顺序排列
|
|
117
|
+
2. 保留段落换行;空行只用于分段,不额外显示
|
|
118
|
+
3. 多条帖子合成一张长图,画布高度按内容长度自动估算
|
|
119
|
+
4. 若帖子过多导致总高度接近上限,优先按语义拆成多张图,不要强行塞满一张
|
|
120
|
+
5. 时间信息默认取帖子 `created_at`;顶部只显示日期,每条帖子底部显示单条发布时间
|
|
121
|
+
|
|
122
|
+
## 时间规则
|
|
123
|
+
|
|
124
|
+
- 时间字段优先使用 `created_at`
|
|
125
|
+
- 不使用 `first_seen_at` 作为新闻发布时间,它只是 ingest 入库时间
|
|
126
|
+
- 当前模板按 `Asia/Shanghai (UTC+8)` 展示时间
|
|
127
|
+
- 顶部只显示日期 `YYYY-MM-DD`
|
|
128
|
+
- 每条帖子底部显示精确到分钟的发布时间
|
|
129
|
+
|
|
130
|
+
## 导出规则
|
|
131
|
+
|
|
132
|
+
- 支持导出到具体位置:`--out` 可传相对路径或绝对路径
|
|
133
|
+
- 脚本会自动创建目标目录
|
|
134
|
+
- 如果后续还要通过消息工具发图,输出仍建议放在当前 workspace 内,避免系统临时目录上传失败
|
|
135
|
+
|
|
136
|
+
## 使用规则
|
|
137
|
+
|
|
138
|
+
- 用户明确提到“X 风格分享图 / 帖子分享图 / 帖子长图”时,优先使用本模板
|
|
139
|
+
- 用户只是要一句金句封面图时,仍使用 `poster-3-4`
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { splitTextByPageMarkers } from "./render-article";
|
|
4
|
+
|
|
5
|
+
describe("splitTextByPageMarkers", () => {
|
|
6
|
+
test("splits chinese page markers into fixed page text segments", () => {
|
|
7
|
+
const result = splitTextByPageMarkers([
|
|
8
|
+
"导语第一行",
|
|
9
|
+
"导语第二行",
|
|
10
|
+
"",
|
|
11
|
+
"【第一页】",
|
|
12
|
+
"第一页正文",
|
|
13
|
+
"",
|
|
14
|
+
"【第二页】",
|
|
15
|
+
"第二页正文",
|
|
16
|
+
].join("\n"));
|
|
17
|
+
|
|
18
|
+
expect(result).toEqual([
|
|
19
|
+
{
|
|
20
|
+
page: 1,
|
|
21
|
+
text: [
|
|
22
|
+
"导语第一行",
|
|
23
|
+
"导语第二行",
|
|
24
|
+
"",
|
|
25
|
+
"第一页正文",
|
|
26
|
+
].join("\n"),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
page: 2,
|
|
30
|
+
text: "第二页正文",
|
|
31
|
+
},
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("supports english page markers", () => {
|
|
36
|
+
const result = splitTextByPageMarkers([
|
|
37
|
+
"【Page 2】",
|
|
38
|
+
"Second page copy",
|
|
39
|
+
"",
|
|
40
|
+
"【Page 3】",
|
|
41
|
+
"Third page copy",
|
|
42
|
+
].join("\n"));
|
|
43
|
+
|
|
44
|
+
expect(result).toEqual([
|
|
45
|
+
{ page: 2, text: "Second page copy" },
|
|
46
|
+
{ page: 3, text: "Third page copy" },
|
|
47
|
+
]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("returns an empty list when there are no page markers", () => {
|
|
51
|
+
expect(splitTextByPageMarkers("纯正文,没有页标记")).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
});
|