convert_markdown_to_docx
Convert Markdown files to professionally styled Word documents with theme options, table of contents, and formatting preservation.
Instructions
Enhanced Markdown to DOCX conversion with professional styling and theme support. Preserves formatting, supports tables, lists, headings, and inline formatting with beautiful Word document output. Output directory is controlled by OUTPUT_DIR environment variable. Files will be automatically saved to OUTPUT_DIR with auto-generated names.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| markdownPath | Yes | Markdown file path to convert | |
| theme | No | Theme to apply | professional |
| includeTableOfContents | No | Generate table of contents | |
| preserveStyles | No | Preserve Markdown formatting and styles |
Implementation Reference
- Exported handler function for the 'convert_markdown_to_docx' tool. Creates converter instance and calls the main conversion method.
export async function convertMarkdownToDocx( inputPath: string, options: MarkdownToDocxOptions = {} ): Promise<MarkdownToDocxResult> { const converter = new MarkdownToDocxConverter(); return await converter.convertMarkdownToDocx(inputPath, options); } - Core implementation of Markdown to DOCX conversion within the converter class: reads file, parses Markdown elements (headings, paragraphs, tables, code blocks, etc.), applies themes and styles using docx library, generates and returns DOCX buffer.
async convertMarkdownToDocx( inputPath: string, options: MarkdownToDocxOptions = {} ): Promise<MarkdownToDocxResult> { try { this.options = { preserveStyles: true, theme: 'default', includeTableOfContents: false, debug: false, ...options, }; if (this.options.debug) { console.log('🚀 开始 Markdown 到 DOCX 转换...'); console.log('📄 输入文件:', inputPath); console.log('🎨 使用主题:', this.options.theme); } // 读取 Markdown 文件 const markdownContent = await fs.readFile(inputPath, 'utf-8'); // 解析 Markdown 内容 const parsedElements = await this.parseMarkdown(markdownContent); // 生成 DOCX 文档 const docxDocument = await this.generateDocxDocument(parsedElements); // 生成文档缓冲区 const docxBuffer = await Packer.toBuffer(docxDocument); // 保存文件(如果指定了输出路径) let docxPath: string | undefined; if (this.options.outputPath) { const { validateAndSanitizePath } = require('../security/securityConfig'); const allowedPaths = [process.cwd()]; const validatedPath = validateAndSanitizePath(this.options.outputPath, allowedPaths); if (validatedPath) { docxPath = validatedPath; await fs.writeFile(validatedPath, docxBuffer); } if (this.options.debug) { console.log('✅ DOCX 文件已保存:', docxPath); } } // 分析内容统计 const stats = this.analyzeContent(parsedElements); if (this.options.debug) { console.log('📊 转换统计:', stats); console.log('✅ Markdown 转换完成'); } return { success: true, content: docxBuffer, docxPath, metadata: { originalFormat: 'markdown', targetFormat: 'docx', stylesPreserved: this.options.preserveStyles ?? false, theme: this.options.theme ?? 'default', converter: 'markdown-to-docx-converter', contentLength: docxBuffer.length, ...stats, }, }; } catch (error: any) { console.error('❌ Markdown 转换失败:', error.message); return { success: false, error: error.message, }; } } - TypeScript interface defining the input parameters/options schema for the conversion tool.
interface MarkdownToDocxOptions { preserveStyles?: boolean; theme?: 'default' | 'professional' | 'academic' | 'modern'; includeTableOfContents?: boolean; customStyles?: { fontSize?: number; fontFamily?: string; lineSpacing?: number; margins?: { top?: number; bottom?: number; left?: number; right?: number; }; }; outputPath?: string; debug?: boolean; } - TypeScript interface defining the output result schema for the tool.
interface MarkdownToDocxResult { success: boolean; content?: Buffer; docxPath?: string; metadata?: { originalFormat: string; targetFormat: string; stylesPreserved: boolean; theme: string; converter: string; contentLength: number; headingsCount: number; paragraphsCount: number; tablesCount: number; }; error?: string; } - Main converter class containing all helper methods for parsing Markdown, generating styled DOCX elements (headings, tables, code blocks, etc.), theme management, and content analysis.
class MarkdownToDocxConverter { private options: MarkdownToDocxOptions = {}; private themes: Map<string, any>; constructor() { this.themes = new Map(); this.initializeThemes(); } /** * 初始化预设主题 */ private initializeThemes(): void { // 默认主题 this.themes.set('default', { fontSize: 11, fontFamily: 'Segoe UI', lineSpacing: 1.15, headingStyles: { h1: { size: 16, color: '2F5496', bold: false }, h2: { size: 13, color: '2F5496', bold: false }, h3: { size: 12, color: '1F3763', bold: false }, h4: { size: 11, color: '2F5496', bold: true }, h5: { size: 11, color: '2F5496', bold: true }, h6: { size: 11, color: '2F5496', bold: true }, }, margins: { top: 1440, bottom: 1440, left: 1440, right: 1440 }, // 1 inch = 1440 twips }); // 专业主题 this.themes.set('professional', { fontSize: 12, fontFamily: 'Segoe UI', lineSpacing: 1.5, headingStyles: { h1: { size: 18, color: '000000', bold: true }, h2: { size: 16, color: '000000', bold: true }, h3: { size: 14, color: '000000', bold: true }, h4: { size: 12, color: '000000', bold: true }, h5: { size: 12, color: '000000', bold: true }, h6: { size: 12, color: '000000', bold: true }, }, margins: { top: 1440, bottom: 1440, left: 1440, right: 1440 }, }); // 学术主题 this.themes.set('academic', { fontSize: 12, fontFamily: 'Segoe UI', lineSpacing: 2.0, headingStyles: { h1: { size: 14, color: '000000', bold: true }, h2: { size: 13, color: '000000', bold: true }, h3: { size: 12, color: '000000', bold: true }, h4: { size: 12, color: '000000', bold: false }, h5: { size: 12, color: '000000', bold: false }, h6: { size: 12, color: '000000', bold: false }, }, margins: { top: 1440, bottom: 1440, left: 1440, right: 1440 }, }); // 现代主题 this.themes.set('modern', { fontSize: 11, fontFamily: 'Segoe UI', lineSpacing: 1.2, headingStyles: { h1: { size: 20, color: '0078D4', bold: true }, h2: { size: 16, color: '0078D4', bold: true }, h3: { size: 14, color: '323130', bold: true }, h4: { size: 12, color: '323130', bold: true }, h5: { size: 11, color: '323130', bold: true }, h6: { size: 11, color: '323130', bold: true }, }, margins: { top: 1440, bottom: 1440, left: 1440, right: 1440 }, }); } /** * 主转换函数 */ async convertMarkdownToDocx( inputPath: string, options: MarkdownToDocxOptions = {} ): Promise<MarkdownToDocxResult> { try { this.options = { preserveStyles: true, theme: 'default', includeTableOfContents: false, debug: false, ...options, }; if (this.options.debug) { console.log('🚀 开始 Markdown 到 DOCX 转换...'); console.log('📄 输入文件:', inputPath); console.log('🎨 使用主题:', this.options.theme); } // 读取 Markdown 文件 const markdownContent = await fs.readFile(inputPath, 'utf-8'); // 解析 Markdown 内容 const parsedElements = await this.parseMarkdown(markdownContent); // 生成 DOCX 文档 const docxDocument = await this.generateDocxDocument(parsedElements); // 生成文档缓冲区 const docxBuffer = await Packer.toBuffer(docxDocument); // 保存文件(如果指定了输出路径) let docxPath: string | undefined; if (this.options.outputPath) { const { validateAndSanitizePath } = require('../security/securityConfig'); const allowedPaths = [process.cwd()]; const validatedPath = validateAndSanitizePath(this.options.outputPath, allowedPaths); if (validatedPath) { docxPath = validatedPath; await fs.writeFile(validatedPath, docxBuffer); } if (this.options.debug) { console.log('✅ DOCX 文件已保存:', docxPath); } } // 分析内容统计 const stats = this.analyzeContent(parsedElements); if (this.options.debug) { console.log('📊 转换统计:', stats); console.log('✅ Markdown 转换完成'); } return { success: true, content: docxBuffer, docxPath, metadata: { originalFormat: 'markdown', targetFormat: 'docx', stylesPreserved: this.options.preserveStyles ?? false, theme: this.options.theme ?? 'default', converter: 'markdown-to-docx-converter', contentLength: docxBuffer.length, ...stats, }, }; } catch (error: any) { console.error('❌ Markdown 转换失败:', error.message); return { success: false, error: error.message, }; } }