145 lines
4.4 KiB
JavaScript
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);
|
|
});
|