md-to-docx
Use this skill to reliably produce .docx output from Markdown.
Workflow
- Decide the execution mode:
- CLI mode for file-to-file conversion.
- Programmatic mode for app code integration.
- Confirm input source (Markdown file or Markdown string).
- Confirm output target (
.docxfile path or browser download). - Apply options only when requested (alignment, sizes, direction, font family, replacements, template, sections, page numbering).
- Run conversion and report resulting output path or filename.
CLI Mode
Use these commands:
npx @mohtasham/md-to-docx input.md output.docx
md-to-docx input.md output.docx
md-to-docx input.md output.docx --options options.json
md-to-docx input.md output.docx -o options.json
md-to-docx --help
CLI contract:
- Required positional args:
<input.md> <output.docx> - Optional options file:
--options <options.json>or-o <options.json> - Options JSON can include the same shapes as the API:
style,template,sections, andtextReplacements - Help flags:
-hor--help - On success, expect:
DOCX created at: <absolute-path>
Programmatic Mode
import { convertMarkdownToDocx, downloadDocx } from "@mohtasham/md-to-docx";
const markdown = "# Title\n\nHello **DOCX**.";
const blob = await convertMarkdownToDocx(markdown, {
documentType: "report",
style: {
fontFamily: "Trebuchet MS",
heading1Alignment: "CENTER",
paragraphAlignment: "JUSTIFIED",
codeBlockAlignment: "LEFT",
direction: "LTR"
}
});
downloadDocx(blob, "output.docx");
Use convertMarkdownToDocx(markdown, options?) to produce a DOCX Blob.
Use downloadDocx(blob, filename?) only in browser environments.
Multi-Section Documents
Use options.template for shared defaults and options.sections for per-section markdown and overrides:
const blob = await convertMarkdownToDocx("", {
template: {
footers: {
default: { pageNumberDisplay: "currentAndTotal", alignment: "CENTER" }
}
},
sections: [
{
markdown: "# Cover Page\n\nIntroduction here.",
titlePage: true,
headers: { first: { text: "Confidential", alignment: "RIGHT" } },
pageNumbering: { start: 1, display: "none" }
},
{
markdown: "# Chapter 1\n\nBody content.",
style: { paragraphAlignment: "JUSTIFIED" },
pageNumbering: { start: 1, display: "currentAndTotal" }
}
]
});
Each section can override: style, headers, footers, pageNumbering, page (margins/size/orientation), titlePage, and type (break type).
Merge precedence:
- Global
styleapplies first templateprovides shared section defaults- Per-section options win last
Use pageNumbering.display for common footer numbering modes: none, current, currentAndTotal, or currentAndSectionTotal.
Text Replacements
Use textReplacements to rewrite text before conversion:
const blob = await convertMarkdownToDocx("# Hello oldText", {
textReplacements: [
{ find: /oldText/g, replace: "newText" },
{ find: "Hello", replace: "Hi" }
]
});
Markdown Features to Expect
Support includes:
- Headings
#to##### - Ordered/unordered lists
- Bold, italic, underline (
++text++), strikethrough (~~text~~) - Custom font family via
fontFamilystyle option - Blockquotes
- Tables (with inline formatting: bold, italic, code, links, strikethrough in cells)
- Code blocks and inline code (with configurable
codeBlockAlignment) - Links and images
- Text replacements before rendering via
textReplacements COMMENT: ...[TOC]on its own line\pagebreakon its own line- Horizontal rules (
---) are skipped during DOCX generation
Style Options Quick Reference
| Option | Values | Default |
|---|---|---|
paragraphAlignment | LEFT, CENTER, RIGHT, JUSTIFIED | LEFT |
headingAlignment | same | LEFT |
heading1Alignment–heading5Alignment | same | LEFT |
blockquoteAlignment | same | LEFT |
codeBlockAlignment | same | LEFT |
fontFamily | any font name string | Calibri |
direction | LTR, RTL | LTR |
tableLayout | autofit, fixed | autofit |
tocFontSize | number | library default |
Troubleshooting
- If CLI fails with argument errors, re-check that exactly two positional paths are provided.
- If options parsing fails, validate JSON syntax and ensure the root is an object.
- If output is missing, verify destination directory permissions and path spelling.
- If in Node and you need a file, write the returned
Blobbytes to disk instead of usingdownloadDocx. - If sections produce unexpected numbering, ensure each section sets
pageNumbering.startto reset counts. - If first-page headers or footers do not appear, set
titlePage: trueon that section.