mrkeyoor.com_
Sat 08 Aug 17:41 UTC
npmUtilsupdated 08 Aug 2026

mammoth

Mammoth converts Microsoft Word .docx documents into semantic HTML by mapping Word paragraph and character styles to elements such as headings, paragraphs, lists, links, tables, footnotes, and images. It can also extract plain text, accept files or buffers in Node, accept ArrayBuffer input in browsers, and apply custom style maps. Its goal is clean content structure rather than visual imitation of Word. That makes it useful for publishing prose authored in Word, but unsuitable for documents whose meaning depends on exact pagination, floating objects, columns, text boxes, or page layout.

Verdict

Mammoth is excellent for turning disciplined, style-driven Word prose into clean web content. It is not a Word renderer, and any upload pipeline must add sanitization, resource limits, message handling, and deliberate image storage.

API stability4/5convertToHtml, extractRawText, embedStyleMap, Node path and buffer input, browser ArrayBuffer input, result.value, result.messages, and styleMap have been established for years. The README clearly marks convertToMarkdown as deprecated and transformDocument as unstable, isolating the risky surfaces. The stable conversion API is dependable, but style mapping is coupled to real Word document structure, so behavioral changes can still appear without a JavaScript signature change.
Docs5/5The README is effectively a full manual: CLI and library use, every input shape, style-map syntax, images, comments, text extraction, embedded mappings, messages, document transforms, and freshness rules all have examples. Its security section explicitly covers javascript: links, external file exfiltration, and denial-of-service risk. It also plainly states that complicated documents will not convert perfectly and that Markdown support is deprecated.
Maintenance4/5npm lists 1.12.0, GitHub was pushed on 2026-05-24, and the repository is not archived. GitHub reports 6,276 stars and 65 open issues and pull requests, while npm metadata includes built-in declarations and Node 12 compatibility. Recent activity is solid for a mature converter. The format's complexity and unstable transform API mean users still depend heavily on one project's interpretation of changing WordprocessingML edge cases.
Ecosystem4/5Mammoth recorded 7,012,028 npm downloads for the week ending 2026-08-06 and has JavaScript, browser, Python, and JVM family implementations referenced by the project. Its semantic HTML output composes with established sanitizers, editors, and HTML-to-Markdown tools. The ecosystem cannot erase the core tradeoff: visual Word rendering, OCR, PDF conversion, and broad office-format extraction belong to different tools.

Use it if

  • You need semantic HTML from reasonably styled .docx articles, reports, or knowledge-base pages
  • You can standardize Word style names and maintain a style map for your publishing model
  • You need Node file or buffer conversion and browser ArrayBuffer conversion from the same package
  • You want to extract document text or images without running Microsoft Office
Skip it if

Setup reality

mammoth 1.12.0 requires Node 12 or newer, bundles TypeScript declarations, and depends on a sizeable pure-JavaScript stack for ZIP and WordprocessingML parsing. In Node, pass {path} or {buffer}; in a browser, pass {arrayBuffer}. Mixing those input shapes is a common first failure. convertToHtml returns a promise containing value and messages, and warnings do not necessarily reject the promise, so log or surface result.messages instead of assuming success means fidelity. The default style map handles common Word styles, but real editorial pipelines need authors to use named styles consistently. Direct formatting and creative document layout do not translate predictably. Custom mappings override defaults; includeDefaultStyleMap: false removes all built-ins, while includeEmbeddedStyleMap: false prevents a document-carried mapping from changing server behavior. Images become data URIs by default, which can make HTML very large. Production systems usually save image buffers to controlled storage and return trusted URLs. Browser image handlers cannot call readAsBuffer without a Buffer polyfill, so use readAsArrayBuffer or readAsBase64String there. The security warning is not optional: Mammoth does no sanitization, .docx links can contain javascript: URLs, and crafted documents may cause pathological CPU or memory use. Keep externalFileAccess false for uploads, sanitize generated HTML with a separate allowlist sanitizer, cap input size, and isolate conversion behind a timeout or worker when documents are untrusted. idPrefix defaults to empty, so multiple converted documents can collide on bookmark, footnote, or endnote IDs when rendered together. Set a unique safe prefix. Markdown conversion is deprecated; convert to HTML and then use a maintained HTML-to-Markdown package. If layout is the requirement, use a renderer or server-side Office/PDF conversion rather than adding more style-map exceptions.

Patterns

Convert a .docx path to HTMLconvert-file

const mammoth = require('mammoth');

const result = await mammoth.convertToHtml(
  { path: 'article.docx' },
  { idPrefix: 'article-42-' }
);
console.log(result.value);
for (const message of result.messages) console.warn(message.type, message.message);

Warnings are returned in messages and may not reject the promise. Set idPrefix when several documents can share a page.

Convert an uploaded Node bufferconvert-buffer

const result = await mammoth.convertToHtml(
  { buffer: uploadedBuffer },
  {
    externalFileAccess: false,
    includeEmbeddedStyleMap: false,
    idPrefix: requestId + '-',
  }
);

Keep externalFileAccess false for uploads. Disabling embedded style maps prevents the document from supplying conversion rules.

Convert a browser Fileconvert-in-browser

import mammoth from 'mammoth/mammoth.browser';

const arrayBuffer = await file.arrayBuffer();
const result = await mammoth.convertToHtml({ arrayBuffer });
preview.innerHTML = DOMPurify.sanitize(result.value);

Browser input uses arrayBuffer, not path or Node Buffer. DOMPurify is a separate dependency; Mammoth output is not sanitized.

Map editorial Word styles to semantic HTMLmap-word-styles

const options = {
  styleMap: [
    "p[style-name='Article Title'] => h1:fresh",
    "p[style-name='Deck'] => p.deck:fresh",
    "p[style-name='Pull Quote'] => blockquote:fresh",
  ],
};
const result = await mammoth.convertToHtml({ path }, options);

Style names must match the source document. Custom mappings take precedence over the default map.

Disable built-in and embedded mappingsuse-only-custom-map

const result = await mammoth.convertToHtml(
  { buffer },
  {
    styleMap: styleMapText,
    includeDefaultStyleMap: false,
    includeEmbeddedStyleMap: false,
  }
);

With defaults disabled, every structure you care about must be covered by your map or Mammoth's fallback behavior.

Extract text without formattingextract-raw-text

const { value: text, messages } = await mammoth.extractRawText({ buffer });
console.log(text);

Formatting is ignored and each paragraph is followed by two newlines. This is extraction, not layout-preserving conversion.

Save extracted images instead of embedding data URLsstore-images

const fs = require('node:fs/promises');
let imageNumber = 0;
const options = {
  convertImage: mammoth.images.imgElement(async (image) => {
    const extension = image.contentType === 'image/png' ? 'png' : 'bin';
    const name = 'image-' + (++imageNumber) + '.' + extension;
    await fs.writeFile('public/uploads/' + name, await image.readAsBuffer());
    return { src: '/uploads/' + name };
  }),
};

Validate content types, generate collision-safe names, and write outside executable paths in real upload systems. readAsBuffer is Node-only.

Expose Word comments in the outputinclude-comments

const result = await mammoth.convertToHtml(
  { path },
  { styleMap: ['comment-reference => sup'] }
);

Comments are ignored by default. When included, comment bodies are appended to the document and references use the mapped element.

Keep empty Word paragraphspreserve-empty-paragraphs

const result = await mammoth.convertToHtml(
  { path },
  { ignoreEmptyParagraphs: false }
);

Empty paragraphs are ignored by default. Preserving them can create presentation-only markup that conflicts with semantic publishing goals.

Sanitize generated HTML on the serversanitize-output

const sanitizeHtml = require('sanitize-html');

const result = await mammoth.convertToHtml({ buffer }, {
  externalFileAccess: false,
  includeEmbeddedStyleMap: false,
});
const safeHtml = sanitizeHtml(result.value, {
  allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']),
  allowedSchemes: ['http', 'https', 'mailto'],
});

sanitize-html is a separate install. Keep javascript and data schemes out unless a reviewed use case requires them.

Write a reusable style map into a documentembed-style-map

const fs = require('node:fs/promises');

const mapped = await mammoth.embedStyleMap(
  { path: 'source.docx' },
  "p[style-name='Section Title'] => h1:fresh"
);
await fs.writeFile('mapped.docx', mapped.toBuffer());

Embedded maps are consumed by default during later conversion. Disable includeEmbeddedStyleMap when documents are untrusted.

Alternatives

PackageRegistryPick it when
docx-previewnpmYou want browser-side visual rendering that tries to resemble the original Word layout
officeparsernpmYou mainly need text extraction from several Office and OpenDocument formats
textractnpmYou need a common text-extraction interface across office files, PDFs, and other document types and accept external-tool setup