Files

81 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
/**
* gen_docx.js
* 通用图文平台发布版docx生成器
*
* 用法:
* node gen_docx.js --title "标题" --subtitle "副标题" --output output.docx \
* --cover ./assets/cover.png \
* --content-json '<JSON_STRING>'
*/
const { Document, Packer, Paragraph, TextRun, ImageRun } = require('/home/node/.openclaw/node_modules/docx');
const fs = require('fs');
const args = process.argv.slice(2);
let title = '', subtitle = '', output = '', coverImg = '';
let contentJson = '';
for (let i = 0; i < args.length; i++) {
if (args[i] === '--title' && args[i+1]) title = args[++i];
else if (args[i] === '--subtitle' && args[i+1]) subtitle = args[++i];
else if (args[i] === '--output' && args[i+1]) output = args[++i];
else if (args[i] === '--cover' && args[i+1]) coverImg = args[++i];
else if (args[i] === '--content-json' && args[i+1]) contentJson = args[++i];
}
if (!output) { console.error('Usage: --output required'); process.exit(1); }
const loadImg = (p) => (p && fs.existsSync(p)) ? fs.readFileSync(p) : null;
const cover = coverImg ? loadImg(coverImg) : null;
const E = () => new Paragraph({ text: '' });
const TITLE = (t) => new Paragraph({ children: [new TextRun({ text: t, bold: true, size: 48 })], alignment: 'center', spacing: { before: 0, after: 160 } });
const SUB = (t) => new Paragraph({ children: [new TextRun({ text: t, size: 24, color: '888888', italics: true })], alignment: 'center', spacing: { before: 0, after: 200 } });
const H2 = (t) => new Paragraph({ children: [new TextRun({ text: t, bold: true, size: 36 })], spacing: { before: 320, after: 160 } });
const H3 = (t) => new Paragraph({ children: [new TextRun({ text: t, bold: true, size: 28 })], spacing: { before: 200, after: 80 } });
const BODY = (t) => new Paragraph({ children: [new TextRun({ text: t, size: 28 })], spacing: { before: 60, after: 80 } });
const EMP = (t) => new Paragraph({ children: [new TextRun({ text: t, bold: true, size: 30 })], spacing: { before: 120, after: 100 } });
const END = (t) => new Paragraph({ children: [new TextRun({ text: t, size: 22, color: 'AAAAAA', italics: true })], alignment: 'center', spacing: { before: 200, after: 0 } });
const IMGP = (d, w, h) => d ? new Paragraph({ children: [new ImageRun({ data: d, transformation: { width: w, height: h }, type: 'png' })], alignment: 'center', spacing: { before: 100, after: 100 } }) : E();
let config = {};
try { config = contentJson ? JSON.parse(contentJson) : {}; } catch(e) { console.error('JSON parse error:', e.message); }
const children = [];
// Cover
if (cover) { children.push(IMGP(cover, 580, 326)); children.push(E()); }
children.push(TITLE(title));
if (subtitle) children.push(SUB(subtitle));
children.push(E());
// Sections
const sections = config.sections || [];
for (const sec of sections) {
if (sec.heading) children.push(H2(sec.heading));
if (sec.image) children.push(E());
if (sec.paragraphs && Array.isArray(sec.paragraphs)) {
for (const p of sec.paragraphs) {
if (!p || p.trim() === '') { children.push(E()); continue; }
const clean = p.trim();
if (clean.length < 60 && clean.match(/^[①②③④]/)) {
children.push(BODY(clean));
} else if (clean.length < 80 && !clean.includes('。')) {
children.push(BODY(clean));
} else {
children.push(BODY(clean));
}
}
}
children.push(E());
}
// Source
if (config.source) children.push(END(config.source));
const doc = new Document({ sections: [{ children }] });
Packer.toBuffer(doc).then(buf => {
fs.writeFileSync(output, buf);
console.log('done');
}).catch(e => { console.error(e); process.exit(1); });