Files
memind/scripts/dryrun-news-morning-draft.mjs
john 2049bc8c6e fix(news): count lead cards in degradation check, add draft dry-run script
Trying to push a WeChat draft locally surfaced two problems.

isNewsMorningContentDegraded matched cards with `class="card(?:\s|")`, which
never matches news002's `class="lead-card"`. Headline cards were therefore
invisible to the check, so a healthy news002 page could be flagged as degraded
and regenerated. Count cards through the shared extractor instead, which
handles card, lead-card and highlight-box alike.

Add scripts/dryrun-news-morning-draft.mjs to run a page through the dedup gate,
degradation check, inline conversion and footer layout without calling the
WeChat API, since local IPs are not in the official account whitelist
(errcode 40164) and a real push would write into the production draft box.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 09:31:54 +08:00

86 lines
3.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* 本地 dry-run:把一张早报 HTML 走完「去重闸门 → 微信 inline 转换 → 统一页脚」全链路,
* 输出最终草稿正文,但不调用任何微信接口、不落 DB。
*
* 用于在本机 IP 不在公众号白名单时验证 news001 / news002 的草稿产出。
*
* 用法:
* node scripts/dryrun-news-morning-draft.mjs <页面.html> [输出目录]
*/
import fs from 'node:fs';
import path from 'node:path';
import {
dedupeNewsMorningHtml,
formatNewsMorningDedupeSummary,
} from '../wechat-news-morning-dedup.mjs';
import {
convertNewsPageHtmlToWechatArticle,
isDailyNewsFormat,
isNewsMorningContentDegraded,
} from '../wechat-news-morning-draft.mjs';
const MAX_WECHAT_CONTENT_CHARS = 20000;
const input = process.argv[2];
const outDir = process.argv[3] || path.dirname(input ?? '.');
if (!input || !fs.existsSync(input)) {
console.error('用法:node scripts/dryrun-news-morning-draft.mjs <页面.html> [输出目录]');
process.exit(1);
}
const publicUrl = 'https://m.tkmind.cn/MindSpace/dry-run/public/daily-news-dryrun.html';
const raw = fs.readFileSync(input, 'utf8');
console.log(`输入:${input}(${raw.length} 字符)`);
// 1. 去重闸门
const deduped = dedupeNewsMorningHtml(raw);
console.log(`\n[1] 去重闸门:${formatNewsMorningDedupeSummary(deduped)}`);
if (deduped.removedSectionIds.length) {
console.log(` 移除空栏目:${deduped.removedSectionIds.join(', ')}`);
}
// 2. 降级检测
const degraded = isNewsMorningContentDegraded(deduped.html);
console.log(`\n[2] 降级检测:${degraded ? '❌ 判定为降级页(卡片不足/检索失败)' : '✅ 正常'}`);
// 3. 识别版式 + 转换为微信草稿
console.log(`\n[3] 版式识别:${isDailyNewsFormat(deduped.html) ? '✅ daily-news' : '❌ 非早报版式'}`);
const article = convertNewsPageHtmlToWechatArticle(
deduped.html,
{ publicUrl, qrcodeImageUrl: 'https://mmbiz.qpic.cn/dryrun-qrcode.png' },
);
console.log('\n[4] 草稿产出:');
console.log(` 标题:${article.title}`);
console.log(` 摘要:${String(article.digest ?? '').slice(0, 60)}`);
console.log(` 正文长度:${article.content.length} / ${MAX_WECHAT_CONTENT_CHARS}`
+ (article.content.length > MAX_WECHAT_CONTENT_CHARS ? ' ❌ 超限' : ' ✅ 未超限'));
const checks = [
// 微信不支持 <style>,早报路径必须全部内联。
['无 <style> 块(已内联)', !/<style/i.test(article.content)],
['正文使用内联 style', (article.content.match(/style="/g) ?? []).length > 20],
['含「阅读原文」引导', /阅读原文/u.test(article.content)],
['含关注二维码区', /<img[^>]+dryrun-qrcode/i.test(article.content)],
['无 <script> 残留', !/<script/i.test(article.content)],
['无 MindSpace 平台水印', !/data-mindspace-page-tag/i.test(article.content)],
];
console.log('\n[5] 合规检查:');
for (const [label, ok] of checks) console.log(` ${ok ? '✅' : '❌'} ${label}`);
const base = path.basename(input, '.html');
const outHtml = path.join(outDir, `${base}.wechat-draft.html`);
fs.writeFileSync(outHtml, `<!DOCTYPE html><html><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>${article.title}(微信草稿 dry-run)</title></head>${article.content}</html>`);
console.log(`\n草稿正文已写入:${outHtml}`);
const outDeduped = path.join(outDir, `${base}.deduped.html`);
if (deduped.changed) {
fs.writeFileSync(outDeduped, deduped.html);
console.log(`去重后页面已写入:${outDeduped}`);
}