0.1.0 β€’ Published 9 months ago

@m2d/remark-docx v0.1.0

Weekly downloads
-
License
MPL-2.0
Repository
github
Last release
9 months ago

@m2d/remark-docx

test codecov Version Downloads Bundle Size

A Unified/Remark plugin that injects a DOCX compiler using mdast2docx and outputs .docx files from Markdown.


🧭 Overview

@m2d/remark-docx enables direct export of Markdown content to Microsoft Word (.docx) using the Unified ecosystem. It seamlessly bridges remark with the mdast2docx compiler and auto-injects common plugins like GFM tables, math, lists, and inline HTML support.

It’s designed for both browser and Node.js environments, handling environment-specific features like image or HTML parsing smartly.


✨ Features

  • πŸ“„ Converts Markdown to .docx using mdast2docx
  • πŸ”Œ Auto-injects plugins for GFM tables, math, lists, images, and HTML
  • 🧠 Smart: excludes DOM-only plugins in Node.js
  • πŸ’₯ Supports both .process() and .processSync() with an async .result
  • πŸ”„ Output as Blob, Buffer, or base64

πŸ“¦ Installation

npm install @m2d/remark-docx docx

Also install any optional plugins you wish to include in your pipeline:

npm install remark-parse remark-gfm remark-math remark-frontmatter

Other package managers:

yarn add @m2d/remark-docx docx
pnpm add @m2d/remark-docx docx

πŸš€ Usage

πŸ”— Browser Example (Async)

import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import remarkFrontmatter from "remark-frontmatter";
import { remarkDocx } from "@m2d/remark-docx";

const processor = unified()
  .use(remarkParse)
  .use(remarkGfm)
  .use(remarkFrontmatter)
  .use(remarkMath)
  .use(remarkDocx);

const downloadDocx = () => {
  processor
    .process(md)
    .then(res => res.result)
    .then(blob => {
      const url = URL.createObjectURL(blob as Blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "document.docx";
      link.click();
      URL.revokeObjectURL(url);
    });
};

⚑ Browser Example (Sync + Async Result)

const { result } = processor.processSync(md) as { result: Promise<Blob> };
result.then(blob => {
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = "document.docx";
  link.click();
  URL.revokeObjectURL(url);
});

🐒 Node.js Example

import fs from "node:fs";
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import remarkFrontmatter from "remark-frontmatter";
import { remarkDocx } from "@m2d/remark-docx";

const markdown = `
# Hello DOCX

This is a *Markdown* document with **tables**, math, and more.

| A | B |
|---|---|
| 1 | 2 |

Inline math: $x^2 + y^2 = z^2$
`;

const processor = unified()
  .use(remarkParse)
  .use(remarkGfm)
  .use(remarkFrontmatter)
  .use(remarkMath)
  .use(remarkDocx, "buffer"); // outputType = "buffer" in Node

const { result } = processor.processSync(markdown) as { result: Promise<Buffer> };

result.then(buffer => {
  fs.writeFileSync("output.docx", buffer);
  console.log("βœ” DOCX file written: output.docx");
});

🧩 Plugin Behavior

By default, these mdast2docx plugins are included:

PluginDescription
htmlPluginParses inline HTML
tablePluginGFM table support
listPluginOrdered/unordered lists
mathPluginKaTeX math blocks
imagePluginResolves images

On Node.js, htmlPlugin and imagePlugin are automatically excluded to avoid DOM dependency issues.

To override this behavior, pass custom plugins using sectionProps.plugins.


πŸ“˜ API

remarkDocx(outputType?, docxProps?, sectionProps?)

ParamTypeDescription
outputType"blob" | "buffer" | "base64"Default is "blob"
docxPropsIDocxPropsGlobal DOCX config (optional)
sectionPropsISectionPropsSection + plugin control (optional)

Returns a Processor where .result on vfile is a Promise<Blob | Buffer | string> depending on the mode.


πŸ”₯ Output Handling

Both .process() and .processSync() return a vfile with a result field:

const file = await processor.process(md);
const blobOrBuffer = await file.result;

This makes the plugin environment-safe and decoupled from internal mutation or I/O.


πŸ›  Development

npm run dev       # Watch mode
npm run build     # Compile to /dist
npm run lint      # Lint source
npm run test      # Run tests

πŸ“„ License

Licensed under the MPL-2.0 License.


πŸ’– Sponsors

Support the project & its ecosystem:


πŸ”— Related Projects