
Research
/Security News
PolinRider Spreads Through Compromised GitHub Accounts and Packagist
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.
@zennomi/markdown-docx
Advanced tools
Convert Markdown files to DOCX format with support for both browser and Node.js environments.
将 Markdown 文件转换为 DOCX 格式,支持浏览器和 Node.js 环境。

$...$, display $$...$$, and fenced math/latex/katex; supports fractions, roots, subscripts/superscripts, sums/integrals with limits, and matrices# Using npm
npm install @zennomi/markdown-docx
# Using yarn
yarn add @zennomi/markdown-docx
# Using pnpm
pnpm add @zennomi/markdown-docx
import fs from 'node:fs/promises';
import markdownDocx, { Packer } from '@zennomi/markdown-docx';
async function convertMarkdownToDocx() {
// Read markdown content
const markdown = await fs.readFile('input.md', 'utf-8');
// Convert to docx
const doc = await markdownDocx(markdown);
// Save to file
const buffer = await Packer.toBuffer(doc);
await fs.writeFile('output.docx', buffer);
console.log('Conversion completed successfully!');
}
convertMarkdownToDocx();
import markdownDocx, { Packer } from '@zennomi/markdown-docx';
async function convertMarkdownToDocx(markdownText) {
// Convert to docx
const doc = await markdownDocx(markdownText);
// Generate blob for download
const blob = await Packer.toBlob(doc);
// Create download link
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'document.docx';
a.click();
// Clean up
URL.revokeObjectURL(url);
}
// Example usage with a textarea
document.getElementById('convert-btn').addEventListener('click', () => {
const markdown = document.getElementById('markdown-input').value;
convertMarkdownToDocx(markdown);
});
npx skills add zennomi/markdown-docx
This skill provides seamless conversion of Markdown files to Microsoft Word DOCX format. Perfect for transforming documentation, notes, and reports into professional Word documents.
For more control over the conversion process, you can use the MarkdownDocx class directly:
import { MarkdownDocx, Packer } from '@zennomi/markdown-docx';
import fs from 'node:fs/promises';
async function convertWithOptions() {
const markdown = await fs.readFile('input.md', 'utf-8');
// Create instance with options
const converter = new MarkdownDocx(markdown)
// Generate document
const doc = await converter.toDocument({
title: 'My Document',
creator: 'markdown-docx',
description: 'Generated from Markdown'
});
// Save to file
const buffer = await Packer.toBuffer(doc);
await fs.writeFile('output.docx', buffer);
}
The MarkdownDocx constructor and markdownDocx function accept an options object with the following properties:
| Option | Type | Default | Description |
|---|---|---|---|
imageAdapter | Function | Built-in adapter | Custom function to handle image processing |
ignoreImage | Boolean | false | When set to true, images in markdown will be ignored |
ignoreFootnote | Boolean | false | When set to true, footnotes will be ignored |
ignoreHtml | Boolean | false | When set to true, inline HTML will be ignored |
gfm | Boolean | true | Enable GitHub Flavored Markdown support |
theme | Object | Default theme | Custom theme configuration for colors and sizes |
Additional options from the marked library are also supported.
interface MathOptions {
engine?: 'builtin' | 'katex' // default: 'katex'
katexOptions?: Record<string, any>
// Prefer constructs that render reliably in LibreOffice
libreOfficeCompat?: boolean
}
Example:
const doc = await markdownDocx(markdown, {
math: {
engine: 'katex',
libreOfficeCompat: false // set true if LibreOffice rendering looks off
}
})
You can customize the appearance of the generated document by providing a theme configuration:
Example:
const docx = await markdownToDocx(markdownText, {
theme: {
// interface IMarkdownTheme Colors (hex values without #)
heading1: "5B21B6",
heading2: "7C3AED",
heading3: "8B5CF6",
heading4: "374151",
heading5: "374151",
heading6: "374151",
link: "00fb0a",
code: "EC4899",
blockquote: "6B7280",
del: "EF4444",
heading1Size: 66,
heading2Size: 52,
heading3Size: 42,
spaceSize: 18,
codeSize: 20,
linkUnderline: false,
}
})
All theme properties are optional - you can override only the properties you want to customize.
markdown-docx includes a CLI tool for converting markdown files from the command line:
# Install globally
npm install -g @zennomi/markdown-docx
# Basic usage
markdown-docx --input input.md --output output.docx
# Short form
markdown-docx -i input.md -o output.docx
If the output file is not specified, it will use the input filename with a .docx extension.
The library supports LaTeX-style mathematical equations using the $ delimiter for inline math and $$ for block equations.
Use single dollar signs for inline equations:
Einstein's famous equation is $E=mc^2$.
The Pythagorean theorem: $a^2 + b^2 = c^2$.
Use double dollar signs for display equations:
$$
E=mc^2
$$
$$
\alpha + \beta + \gamma = \pi
$$
You can also use fenced code blocks labeled math, latex, or katex for display equations:
```math
\left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right)
### Supported Features
- **Superscripts**: `$x^2$`, `$e^{10}$`
- **Subscripts**: `$x_1$`, `$a_{10}$`
- **Greek letters**: `$\alpha$`, `$\beta$`, `$\gamma$`, `$\pi$`, `$\omega$`, etc.
- **Operators**: `$\times$`, `$\div$`, `$\pm$`, `$\mp$`
- **Relations**: `$\leq$`, `$\geq$`, `$\neq$`, `$\approx$`, `$\equiv$`
- **Special symbols**: `$\infty$`, `$\in$`, `$\notin$`
By default, equations are rendered via KaTeX (LaTeX → MathML → native Word math/OMML) for broad coverage.
You can opt out to the lightweight builtin renderer (LaTeX → Unicode) if you prefer minimal output:
```ts
import markdownDocx, { Packer } from '@zennomi/markdown-docx'
// Fallback to builtin (simple text) renderer
const doc = await markdownDocx(markdown, {
math: { engine: 'builtin' }
})
LibreOffice has partial OMML support. If equations look wrong in LibreOffice, enable a compatibility mode that favors simpler constructs:
import markdownDocx, { Packer } from '@zennomi/markdown-docx'
const doc = await markdownDocx(markdown, {
math: {
engine: 'katex',
libreOfficeCompat: true
}
})
With KaTeX (default), structures like \frac{a}{b}, x^{2}, x_{i}, \sqrt{x}, \sum/\int with limits, and basic matrices render as native Word math.
The library provides a built-in image adapter that automatically downloads images from URLs. You can also create a custom image adapter by implementing the ImageAdapter interface.
The adapter should have a getImage method that takes an image URL and returns a Promise that resolves to an object containing the image data.
const imageAdapter: (token: Tokens.Image) => Promise<null | MarkdownImageItem>
You can specify custom image dimensions in the Markdown image title attribute using the format widthxheight (e.g., 600x400 or 30%x30%). This will override the original image dimensions when rendering in the DOCX document, which is useful for controlling image size and avoiding Word's maximum width constraints.


The custom dimensions will be applied to the image in the generated DOCX file, while the original image data remains unchanged.
You can customize the styling of the generated DOCX by accessing the style components:
import { styles, colors, classes, numbering } from '@zennomi/markdown-docx';
// Example: customize docs link color
styles.default.hyperlink.run.color = '0077cc';
styles.markdown.code.run.color = '000000';
You can refer to the files in src/styles to write your own styles.
The library automatically detects the environment and uses the appropriate image adapter:
For more examples, see the tests directory in the repository.
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
Convert Markdown file to DOCX format
The npm package @zennomi/markdown-docx receives a total of 2 weekly downloads. As such, @zennomi/markdown-docx popularity was classified as not popular.
We found that @zennomi/markdown-docx demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.

Company News
Allow myself to introduce... myself.