Files
memind/scripts/preview-wechat-draft-layout.mjs
T
john b6d85d487a
Memind CI / Test, build, and release guards (push) Failing after 2m51s
Update WeChat draft follow template
2026-09-14 15:36:40 +08:00

145 lines
4.4 KiB
JavaScript

#!/usr/bin/env node
/**
* 生成公众号草稿底部 layout 样板页(阅读原文引导 + TKMind 关注二维码)。
*
* 用法:
* node scripts/preview-wechat-draft-layout.mjs [publicUrl] [outputPath]
*/
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import {
applyWechatDraftArticleLayout,
resolveMpFollowQrcodePublicUrl,
} from '../wechat-draft-article-layout.mjs';
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
const userId = '1c99b83b-0454-474f-a5d2-129d34506a32';
const defaultPublicUrl = `https://m.tkmind.cn/MindSpace/${userId}/public/august-afternoon.html`;
async function loadSampleBody() {
const samplePath = path.join(root, 'MindSpace', userId, 'public', 'august-afternoon.html');
try {
const html = await fs.readFile(samplePath, 'utf8');
const titleMatch = html.match(/<title>([^<]+)<\/title>/i);
const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
const text = String(bodyMatch?.[1] ?? '')
.replace(/<script[\s\S]*?<\/script>/gi, '')
.replace(/<style[\s\S]*?<\/style>/gi, '')
.replace(/<[^>]+>/g, ' ')
.replace(/\s+/g, ' ')
.trim()
.slice(0, 480);
return {
title: titleMatch?.[1]?.trim() || 'MindSpace 页面样板',
excerpt: text || '这是一段示例正文,推送到公众号后会自动转换为微信兼容格式。',
};
} catch {
return {
title: 'MindSpace 页面样板',
excerpt: '这是一段示例正文。完整网页版包含更丰富的排版、动画与互动内容,请点击下方「阅读原文」查看。',
};
}
}
function renderPreviewHtml({ title, excerpt, articleContent, publicUrl, qrcodeUrl }) {
return `<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>公众号草稿 layout 样板 · ${title}</title>
<style>
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
background: #ededed;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
color: #111;
}
.phone {
max-width: 420px;
margin: 24px auto;
background: #fff;
border-radius: 18px;
overflow: hidden;
box-shadow: 0 12px 40px rgba(0,0,0,.12);
}
.status {
padding: 10px 16px;
background: #f7f7f7;
font-size: 12px;
color: #666;
border-bottom: 1px solid #eee;
}
.article {
padding: 18px 16px 24px;
line-height: 1.75;
font-size: 16px;
}
.article h1 {
margin: 0 0 12px;
font-size: 22px;
line-height: 1.35;
}
.article p { margin: 0 0 14px; color: #333; }
.meta {
max-width: 420px;
margin: 0 auto 24px;
padding: 0 8px;
font-size: 12px;
color: #666;
line-height: 1.6;
}
.meta code { background: rgba(0,0,0,.06); padding: 1px 4px; border-radius: 4px; }
</style>
</head>
<body>
<div class="phone">
<div class="status">微信草稿箱 · 排版样板(非真实推送)</div>
<article class="article">
<h1>${title}</h1>
<p>${excerpt}</p>
${articleContent}
</article>
</div>
<div class="meta">
<p>阅读原文跳转:<code>${publicUrl}</code></p>
<p>二维码静态资源:<code>${qrcodeUrl}</code></p>
<p>由 <code>scripts/preview-wechat-draft-layout.mjs</code> 生成,用于确认「阅读原文」引导与关注区二维码尺寸。</p>
</div>
</body>
</html>`;
}
async function main() {
const publicUrl = process.argv[2]?.trim() || defaultPublicUrl;
const outputPath = path.resolve(
process.argv[3] || path.join(root, 'public/dev/wechat-draft-layout-preview.html'),
);
const sample = await loadSampleBody();
const qrcodeUrl = resolveMpFollowQrcodePublicUrl(process.env);
const articleContent = applyWechatDraftArticleLayout(
`<p>${sample.excerpt}</p>`,
{ publicUrl, qrcodeImageUrl: qrcodeUrl },
);
const html = renderPreviewHtml({
title: sample.title,
excerpt: sample.excerpt,
articleContent,
publicUrl,
qrcodeUrl,
});
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, html, 'utf8');
console.log(`样板页已写入 ${outputPath}`);
console.log(`publicUrl: ${publicUrl}`);
console.log(`qrcode: ${qrcodeUrl}`);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});