From 3aafe60463e47ae9fa78d05c9b62c7eb7c9a8b2f Mon Sep 17 00:00:00 2001
From: Go1dFinger
Date: Sun, 24 May 2026 18:55:59 -0500
Subject: [PATCH] fix(baoyu-post-to-wechat): improve newspic plain text
conversion for WeChat API
The previous fix used a simple regex to strip HTML tags for newspic
content, but it had several issues:
1. HTML entities ( , <, >, &, etc.) were not decoded
2. Block-level tags (
, , etc.) did not produce line breaks
3. Multiple consecutive whitespace characters were not collapsed
This commit introduces a dedicated htmlToPlainText() function that:
- Converts
and block-level closing tags to line breaks
- Strips all remaining HTML tags
- Decodes common HTML entities (including numeric entities)
- Collapses consecutive whitespace into single spaces
- Trims whitespace from each line
This ensures the content field for newspic articles is properly
formatted plain text that complies with WeChat API requirements,
preventing error 45166 (invalid content) especially when publishing
with multiple images.
Closes #163
Merges #164
---
.../scripts/wechat-api.ts | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/skills/baoyu-post-to-wechat/scripts/wechat-api.ts b/skills/baoyu-post-to-wechat/scripts/wechat-api.ts
index 5b7674e..5656da9 100644
--- a/skills/baoyu-post-to-wechat/scripts/wechat-api.ts
+++ b/skills/baoyu-post-to-wechat/scripts/wechat-api.ts
@@ -99,6 +99,60 @@ function toHttpsUrl(url: string | undefined): string {
return url.startsWith("http://") ? url.replace(/^http:\/\//i, "https://") : url;
}
+function htmlToPlainText(html: string): string {
+ if (!html) return "";
+
+ let text = html;
+
+ // 1. 将
,
,
替换为换行符
+ text = text.replace(/
/gi, "\n");
+
+ // 2. 将 , , , , , , , , 替换为换行符
+ text = text.replace(/<\/(?:p|div|h[1-6]|li|tr|td|th)>/gi, "\n");
+
+ // 3. 去掉所有剩余的 HTML 标签
+ text = text.replace(/<[^>]+>/g, "");
+
+ // 4. 解码 HTML 实体
+ const entityMap: Record = {
+ " ": " ",
+ "<": "<",
+ ">": ">",
+ "&": "&",
+ """: '"',
+ "'": "'",
+ "'": "'",
+ "—": "—",
+ "–": "–",
+ "…": "…",
+ "“": """,
+ "”": """,
+ "‘": "'",
+ "’": "'",
+ };
+ text = text.replace(/&(?:[a-zA-Z]+|#\d+);/g, (entity) => {
+ if (entityMap[entity]) return entityMap[entity];
+ // 处理数字实体,如 {
+ const numMatch = entity.match(/(\d+);/);
+ if (numMatch) {
+ return String.fromCharCode(Number.parseInt(numMatch[1]!, 10));
+ }
+ return entity;
+ });
+
+ // 5. 合并多个连续空白字符(空格、制表符、换行)为一个空格
+ text = text.replace(/[ \t]+/g, " ");
+
+ // 6. 合并多个连续换行为一个换行
+ text = text.replace(/\n{3,}/g, "\n\n");
+
+ // 7. 去掉行首行尾空白
+ text = text.split("\n").map(line => line.trim()).join("\n");
+
+ // 8. 最终 trim
+ return text.trim();
+}
+
async function uploadImage(
imagePath: string,
accessToken: string,
@@ -295,10 +349,15 @@ async function publishToDraft(
if (!options.imageMediaIds || options.imageMediaIds.length === 0) {
throw new Error("newspic requires at least one image");
}
+ // newspic 的 content 应该是纯文本,需要:
+ // 1. 去掉 HTML 标签
+ // 2. 解码 HTML 实体( 、< 等)
+ // 3. 合并多余空白字符
+ const plainContent = htmlToPlainText(options.content);
article = {
article_type: "newspic",
title: options.title,
- content: options.content,
+ content: plainContent,
need_open_comment: noc,
only_fans_can_comment: ofcc,
image_info: {