110 lines
2.8 KiB
TypeScript
110 lines
2.8 KiB
TypeScript
import {
|
|
Document,
|
|
Paragraph,
|
|
TextRun,
|
|
HeadingLevel,
|
|
Packer,
|
|
AlignmentType,
|
|
} from 'docx';
|
|
|
|
export async function generateDocx(
|
|
content: string,
|
|
toolName: string
|
|
): Promise<Buffer> {
|
|
const lines = content.split('\n');
|
|
const children: Paragraph[] = [];
|
|
|
|
// Title
|
|
children.push(
|
|
new Paragraph({
|
|
children: [
|
|
new TextRun({
|
|
text: `NGO Toolkit Lab — ${toolName.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase())}`,
|
|
bold: true,
|
|
size: 32,
|
|
color: '1a6b3c',
|
|
}),
|
|
],
|
|
heading: HeadingLevel.TITLE,
|
|
alignment: AlignmentType.CENTER,
|
|
spacing: { after: 400 },
|
|
})
|
|
);
|
|
|
|
for (const line of lines) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed) {
|
|
children.push(new Paragraph({ spacing: { after: 100 } }));
|
|
continue;
|
|
}
|
|
|
|
if (trimmed.startsWith('### ')) {
|
|
children.push(
|
|
new Paragraph({
|
|
children: [new TextRun({ text: trimmed.slice(4), bold: true, size: 24 })],
|
|
heading: HeadingLevel.HEADING_3,
|
|
spacing: { before: 200, after: 100 },
|
|
})
|
|
);
|
|
} else if (trimmed.startsWith('## ')) {
|
|
children.push(
|
|
new Paragraph({
|
|
children: [new TextRun({ text: trimmed.slice(3), bold: true, size: 28, color: '1a6b3c' })],
|
|
heading: HeadingLevel.HEADING_2,
|
|
spacing: { before: 300, after: 150 },
|
|
})
|
|
);
|
|
} else if (trimmed.startsWith('# ')) {
|
|
children.push(
|
|
new Paragraph({
|
|
children: [new TextRun({ text: trimmed.slice(2), bold: true, size: 32, color: '1a6b3c' })],
|
|
heading: HeadingLevel.HEADING_1,
|
|
spacing: { before: 400, after: 200 },
|
|
})
|
|
);
|
|
} else if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
|
|
children.push(
|
|
new Paragraph({
|
|
children: [new TextRun({ text: trimmed.slice(2), size: 22 })],
|
|
bullet: { level: 0 },
|
|
})
|
|
);
|
|
} else if (trimmed.startsWith('**') && trimmed.endsWith('**')) {
|
|
children.push(
|
|
new Paragraph({
|
|
children: [new TextRun({ text: trimmed.slice(2, -2), bold: true, size: 22 })],
|
|
})
|
|
);
|
|
} else {
|
|
children.push(
|
|
new Paragraph({
|
|
children: [new TextRun({ text: trimmed, size: 22 })],
|
|
spacing: { after: 100 },
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
// Footer
|
|
children.push(
|
|
new Paragraph({
|
|
children: [
|
|
new TextRun({
|
|
text: 'Generated by NGO Toolkit Lab — ngotoolkit.com',
|
|
italics: true,
|
|
size: 18,
|
|
color: '888888',
|
|
}),
|
|
],
|
|
alignment: AlignmentType.CENTER,
|
|
spacing: { before: 600 },
|
|
})
|
|
);
|
|
|
|
const doc = new Document({
|
|
sections: [{ children }],
|
|
});
|
|
|
|
return Buffer.from(await Packer.toBuffer(doc));
|
|
}
|