# Word to Markdown (DOCX → Markdown converter) [![npm version](https://img.shields.io/npm/v/word-to-markdown.svg)](https://www.npmjs.com/package/word-to-markdown) [![npm downloads](https://img.shields.io/npm/dm/word-to-markdown.svg)](https://www.npmjs.com/package/word-to-markdown) [![MCP registry](https://img.shields.io/badge/MCP_registry-io.github.benbalter%2Fword--to--markdown-blue)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.benbalter/word-to-markdown) [![CI](https://github.com/benbalter/word-to-markdown-js/actions/workflows/ci.yml/badge.svg)](https://github.com/benbalter/word-to-markdown-js/actions/workflows/ci.yml) [![License: Apache-2.0](https://img.shields.io/npm/l/word-to-markdown.svg)](https://github.com/benbalter/word-to-markdown-js/blob/main/LICENSE) Convert Word documents to beautiful Markdown. Via command line, as a Node library, or in your browser. An even better version of the original [`word-to-markdown`](https://github.com/benbalter/word-to-markdown). Try it in your browser at [word2md.com](https://word2md.com), or use it from the command line — no clone required: ```console npx word-to-markdown input.docx > output.md ``` ## What it converts - Paragraphs and line breaks - Headings - Bold, italic, and strikethrough - Superscript and subscript — preserved as inline ``/`` tags - Bullet lists, and numbered lists (kept as `1./2./3.` by default) - Nested lists - Tables - Links - Footnotes and endnotes — converted to GFM/Pandoc `[^1]` footnotes - Images — embedded inline as base64 data URIs, or extracted to files - Equations — converted to LaTeX: inline `$…$`, or a `$$` block for an equation on its own line ### Notes and limitations - **Numbered lists** are kept as `1./2./3.` ordered lists, numbered as Word numbers them, so a list interrupted by a paragraph, table, or another list continues where it left off. Pass `{ numberedLists: 'bullets' }` (library) or `--bullet-lists` (CLI) to convert them to bullet lists instead (matching the original word-to-markdown). Outline numbering that repeats the parent's number, like contracts' `1.` → `1.1`, `1.2`, is written out as text (`## 1. Scope`, `1.1 Purpose`), since Markdown lists can't show it. - **Images** are inlined as base64 data URIs by default. To extract them to files with relative links instead, use `{ images: 'extract' }` (library — the bytes come back on `ConvertResult.images`) or `--image-dir ` (CLI). Drop them entirely with `{ images: 'strip' }` / `--strip-images`. On the web, documents with images offer a **Download .zip** (Markdown + an `images/` folder). For full control, pass a custom [Mammoth image handler](https://github.com/mwilliamson/mammoth.js/#images) via `options.mammoth`. - **Underline** is dropped by default (Mammoth's default, since underlines are easily confused with links). Pass `{ underline: 'preserve' }` (library) or `--underline` (CLI) to keep it as an inline `` tag. - **Curly quotes** (“ ” ‘ ’) are kept when the text is mostly Chinese, where they are the Chinese quotation marks, and converted to ASCII everywhere else. Word writes the same code points for English curly quotes, so a quote can't be classified on its own. Pass `{ quotes: 'ascii' }` (library) or `--quotes ascii` (CLI) to always convert, or `'preserve'` / `--quotes preserve` to always keep them. - **Footnotes and endnotes** become standard GFM/Pandoc footnotes — a `[^1]` reference in the body and a `[^1]: …` definition at the end — which render on GitHub and in the web preview. Pass `{ footnotes: 'preserve' }` (library) or `--preserve-footnotes` (CLI) to instead keep Mammoth's raw `` links and numbered note list (useful for CommonMark targets that lack footnote support). Notes whose bodies span multiple paragraphs are converted with indented continuation paragraphs. - **Text boxes** are converted as paragraphs after the containing paragraph. A text box saved without Word's VML fallback (as some other tools write them) is dropped, and `convertWithWarnings` warns. - **Comments** are dropped during the `.docx` → HTML step, and `convertWithWarnings` warns with how many had text. To keep them, map them in a Mammoth style map, e.g. `{ mammoth: { styleMap: ['comment-reference => sup'] } }`. - **Headers and footers** are dropped. `convertWithWarnings` warns when one has text beyond a page number. - **Equations** (Office Math) become LaTeX: inline `$…$`, or a `$$…$$` block when the equation is on its own line, which GitHub and most Markdown math renderers (KaTeX, MathJax) display. Fractions, scripts, roots, sums and integrals, brackets, functions and limits, accents, and matrices are converted. Pass `{ equations: 'strip' }` (library) or `--strip-equations` (CLI) to drop them instead, with a `convertWithWarnings` warning. - Heading levels come from Word's paragraph styles, not from font size. ## How is this different from the original? _TL;DR: This project is a complete rewrite, using modern tools and libraries, and is much faster and more reliable. The output should be the same or better. [Feedback welcome!](https://github.com/benbalter/word-to-markdown-js/issues/new)_ ## A note on privacy Word to Markdown is designed with privacy as a core principle. The application operates entirely client-side: - **Complete client-side processing**: When using the web interface, all document conversion happens locally in your browser using JavaScript. Your documents never leave your computer. - **No server uploads**: When using the web interface, files are processed entirely on your device. No document content is ever transmitted to any server. - **No personal data collection**: The application does not collect, store, or transmit any personal information or document contents. - **Privacy-first analytics**: The hosted version at word2md.com uses only privacy-centric Cloudflare Analytics for anonymous usage statistics. No Google Analytics or user tracking. - **Self-hosting option**: For maximum privacy, you can run the application locally or self-host it without any analytics whatsoever. Whether you use the command line tool, run it locally in your browser, or use the hosted version, your documents and privacy are protected. ## Command line Run it directly with `npx` (downloads and runs the latest published version): ```console npx word-to-markdown path/to/your/file.docx > output.md ``` Or install it globally to get the `w2m` command: ```console npm install -g word-to-markdown w2m path/to/your/file.docx > output.md ``` The converted Markdown is written to **stdout** and any document warnings (encryption, sensitivity labels, and the like) to **stderr**, so a redirect captures only the Markdown. The command exits with status 1 and a friendly message if the file is missing, unreadable, or not a valid `.docx`. Only `.docx` is supported — re-save older `.doc` files as `.docx` first. To read the document from **stdin**, pass `-` as the file, or leave it out and pipe the file in: ```console cat report.docx | w2m > report.md curl -sL https://example.com/report.docx | w2m - -o report.md ``` Options: - `-o, --output ` — write the Markdown to `` instead of stdout (warnings still go to stderr). `-o -` means stdout. - `--bullet-lists` — convert numbered lists to bullets instead of keeping `1./2./3.`. - `--underline` — preserve underlined text as inline `` tags (dropped by default). - `--strip-images` — remove images instead of embedding them as base64 data URIs. - `--image-dir ` — extract images to `` and link them relatively, instead of embedding base64. Links resolve relative to where you save the Markdown, e.g. `w2m --image-dir images report.docx > report.md`, or with `-o`, `w2m -o out/report.md --image-dir images report.docx` (images land in `out/images/`). - `--preserve-footnotes` — keep Word footnotes as raw `` links and a numbered note list instead of GFM `[^1]` footnotes. - `--strip-equations` — drop Word equations instead of converting them to LaTeX. - `--quotes