npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jonathanhotono/browser-docx-merger

v1.1.0

Published

A comprehensive TypeScript library for merging DOCX files in the browser with full style, numbering, and relationship support

Readme

Browser DOCX Merger

A comprehensive TypeScript library for merging DOCX files directly in the browser with full support for styles, numbering, footnotes, endnotes, and media files.

npm version License TypeScript

Features

  • Browser-only - No server required, works entirely in the browser
  • TypeScript support - Full type definitions included
  • Multiple formats - ESM and IIFE global builds
  • Comprehensive merging - Styles, numbering, footnotes, themes, and more
  • Flexible insertion - Pattern-based, start, or end insertion
  • Media handling - Automatic copying and deduplication of images and other media
  • Relationship mapping - Proper handling of document relationships
  • Page breaks - Optional page break insertion between documents
  • Multiple input formats - Accepts File, Blob, ArrayBuffer, Uint8Array, base64 string, or base64 data URI

Installation

NPM

npm install @jonathanhotono/browser-docx-merger

CDN (Browser Global)

<script src="https://unpkg.com/@jonathanhotono/browser-docx-merger/dist/index.global.js"></script>

Usage

ES Modules

import { mergeDocxFromFiles, triggerDownload } from '@jonathanhotono/browser-docx-merger';

const files = Array.from(fileInput.files); // File objects from input
const options = {
  pattern: 'MERGE_HERE', // Insert at paragraphs containing this text
  mergeStyles: true,
  mergeNumbering: true,
  mergeFootnotes: true,
  pageBreaks: true,
  onLog: (message, level) => console.log(`[${level}] ${message}`)
};

try {
  const mergedBlob = await mergeDocxFromFiles(files, options);
  const url = URL.createObjectURL(mergedBlob);
  triggerDownload(url, 'merged-document.docx');
} catch (error) {
  console.error('Merge failed:', error);
}

Browser Global

<script src="https://unpkg.com/@jonathanhotono/browser-docx-merger/dist/index.global.js"></script>
<script>
  // Available as window.DocxMerger
  async function mergeFiles(files) {
    const merged = await DocxMerger.mergeDocxFromFiles(files, {
      insertEnd: true,
      mergeStyles: true
    });
    DocxMerger.triggerDownload(URL.createObjectURL(merged), 'merged.docx');
  }
</script>

Direct Buffer / Mixed Inputs

import { mergeDocx } from '@jonathanhotono/browser-docx-merger';

const base64Doc = 'UEsDBBQABgAIAAAAIQC...' // trimmed raw base64 (no data uri prefix)
const dataUriDoc = 'data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,UEsDBBQABg...';

const inputs = [
  new Uint8Array(docx1ArrayBuffer),
  base64Doc,          // raw base64
  dataUriDoc,         // data URI
  someBlob,           // Blob
  anotherArrayBuffer  // ArrayBuffer
];

const mergedBlob = await mergeDocx(inputs, {
  insertEnd: true,
  mergeStyles: true
});

Base64 Input Notes

  • Raw base64 strings and data:*;base64,... URIs are both accepted.
  • Whitespace and newlines are stripped automatically.

API Reference

mergeDocxFromFiles(files, options?)

Merges multiple DOCX files from File objects.

Parameters:

  • files: File[] - Array of File objects (from file input)
  • options?: MergeOptions - Merge configuration

Returns: Promise<Blob> - The merged DOCX as a Blob

mergeDocx(inputs, options?)

Merges multiple DOCX files from a heterogeneous set of inputs.

Parameters:

  • inputs: (ArrayBuffer|Uint8Array|Blob|string)[] - Array of document sources (string = base64 or data URI)
  • options?: MergeOptions - Merge configuration

Returns: Promise<Blob> - The merged DOCX as a Blob

triggerDownload(url, filename)

Triggers a browser download of the merged document.

Parameters:

  • url: string - Object URL of the Blob
  • filename: string - Desired filename for download

Options

interface MergeOptions {
  // Insertion mode (exactly one must be specified)
  pattern?: string;          // Insert before paragraphs containing this text
  insertStart?: boolean;     // Insert at document start
  insertEnd?: boolean;       // Insert at document end
  
  // Content merging options
  mergeStyles?: boolean;     // Merge styles.xml, fontTable.xml, theme.xml, etc. (default: true)
  mergeNumbering?: boolean;  // Merge numbering definitions (default: true)
  mergeFootnotes?: boolean;  // Merge footnotes and endnotes (default: true)
  pageBreaks?: boolean;      // Add page breaks between documents (default: true)
  
  // Logging
  onLog?: (message: string, level: 'info'|'ok'|'warn'|'err') => void;
}

Style Merging Features

The library provides comprehensive style merging including:

  • Basic Styles (styles.xml) - Character, paragraph, table, and numbering styles
  • Font Tables (fontTable.xml) - Font definitions and substitutions
  • Document Themes (theme1.xml) - Color schemes, fonts, and effects
  • Web Settings (webSettings.xml) - Web-specific styling options
  • Document Settings (settings.xml) - Style-related document settings
  • Automatic Relationships - Proper relationship mapping for all style parts

Examples

Pattern-Based Merging

// Insert documents before paragraphs containing "INSERT_DOCS_HERE"
const merged = await mergeDocxFromFiles(files, {
  pattern: 'INSERT_DOCS_HERE',
  mergeStyles: true,
  pageBreaks: true
});

Sequential Merging

// Append all documents to the end with page breaks
const merged = await mergeDocxFromFiles(files, {
  insertEnd: true,
  pageBreaks: true,
  mergeStyles: true,
  mergeNumbering: true
});

Custom Logging

const merged = await mergeDocxFromFiles(files, {
  insertEnd: true,
  onLog: (message, level) => {
    const emoji = { info: 'ℹ️', ok: '✅', warn: '⚠️', err: '❌' }[level];
    console.log(`${emoji} ${message}`);
  }
});

Browser Compatibility

  • Chrome 61+
  • Firefox 60+
  • Safari 11+
  • Edge 16+

Requires support for:

  • ES2020 features
  • Blob constructor
  • DOMParser/XMLSerializer
  • Promise
  • Uint8Array

Development

# Install dependencies
npm install

# Build library
npm run build

# Run tests
npm test

# Start development server with demo
npm run dev

Demo

Demo site: https://jonathan.hotono.net/docx-merger/

Run the demo locally on demo/:

npm run preview

Then open http://localhost:5173

License

MIT License - see LICENSE file for details.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Submit a pull request

Support

Changelog

v1.1.0

  • Added base64 and data URI input support for mergeDocx
  • Documentation updated with mixed input examples

v1.0.0

  • Initial release
  • Full DOCX merging support
  • Comprehensive style handling
  • TypeScript definitions
  • Browser and Node.js compatibility

Demo Features:

  • Document list showing filename and size
  • Drag-and-drop reordering of documents
  • Remove individual documents
  • Visual feedback during drag operations

Basic usage

ESM:

import { mergeDocx } from 'browser-doc-merger';

const blob = await mergeDocx([file1, file2, file3], {
  insertEnd: true,
  pageBreaks: true,
});

Browser (IIFE bundle):

<script src="./dist/index.global.js"></script>
<script>
  const blob = await window.DocxMerger.mergeDocxFromFiles(files, { insertEnd: true });
</script>

Notes

  • The first file acts as the base; others are inserted.
  • Headers/footers from appended docs aren’t imported; section settings from base remain.
  • For large files, merging is CPU/IO bound; avoid blocking the UI thread if integrating into bigger apps.