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, }; } }